diff --git a/toGPA_G1_G6_MinMaxVectorPlots/AustinG1G6.m b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/AustinG1G6.m similarity index 94% rename from toGPA_G1_G6_MinMaxVectorPlots/AustinG1G6.m rename to Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/AustinG1G6.m index 9cd69db..0e50dea 100644 --- a/toGPA_G1_G6_MinMaxVectorPlots/AustinG1G6.m +++ b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/AustinG1G6.m @@ -1,41 +1,53 @@ -clc -clear all - -currentFolder = pwd; -folderPath = horzcat(currentFolder,'\Input') -D = genpath(folderPath); -fileFolders = split(D,';'); -max = size(fileFolders); -max = max(1,1); -i = 0; -for i = 2:max - fileFolders{i,1}; - currentfile = string(fileFolders{i,1}); - S = strcat(currentfile,'\','*.DAT'); - - files = dir(S); - for file = files' - the_size = file.bytes; - if the_size > 10000 - dat_file = strcat(currentfile,'\',file.name); - dat_file = char(dat_file); - cfg_file = strcat(dat_file(1:end-3),'CFG'); - waveFormCfg = readCFG_COMTRADE(cfg_file); - waveFormDat = readDAT_COMTRADE(dat_file,waveFormCfg); - [Imat,Vmat,~,~] = groupVoltCurr(waveFormDat.analog); - group6PlotV3(waveFormCfg,Vmat,Imat,dat_file,currentFolder,i); - i = i + 1 - end +function tags = group6PlotV3Analytic(Voltage, Current, Fs, Setting) + tags = []; + if ~Setting.ExecuteAnalytic + return end -end - - - - + Vmat = []; + Imat = []; + Vmat = cat(1, Vmat, Voltage(:,1)'); % VX1 + Vmat = cat(1, Vmat, Voltage(:,2)'); % VX2 + Vmat = cat(1, Vmat, Voltage(:,3)'); % VX3 + Vmat = cat(1, Vmat, Voltage(:,4)'); % VY1 + Vmat = cat(1, Vmat, Voltage(:,5)'); % VY2 + Vmat = cat(1, Vmat, Voltage(:,6)'); % VY3 + Imat = cat(1, Imat, Current(:,1)'); % I1 + Imat = cat(1, Imat, Current(:,2)'); % I2 + Imat = cat(1, Imat, Current(:,3)'); % I3 + + cfg = struct; + cfg.station_name = convertStringsToChars(Setting.Station); + cfg.recording_device = convertStringsToChars(Setting.Device); + cfg.lf = Setting.SystemFrequency; + cfg.samp = Fs; + cfg.endsamp = Setting.SampleCount; + cfg.startdate = convertStringsToChars(Setting.EventDate); + cfg.starttime = convertStringsToChars(Setting.EventTime); + + dat_file = convertStringsToChars(Setting.InputFilename); + outputFolder = convertStringsToChars(Setting.OutputFolder); + + result = group6PlotV3(cfg, Vmat, Imat, dat_file, outputFolder, 0); + + if isfield(result, 'g1PlotFilePath') + tag = struct; + tag.Name = 'G1 Vector Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.g1PlotFilePath; + tags = [tags, tag]; + end + if isfield(result, 'g6PlotFilePath') + tag = struct; + tag.Name = 'G6 MinMax Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.g6PlotFilePath; + tags = [tags, tag]; + end +end -function group6PlotV3(wfCfg,Vmat,Imat,dat_file,currentFolder,i) +function sb = group6PlotV3(wfCfg,Vmat,Imat,dat_file,currentFolder,i) try @@ -331,6 +343,7 @@ function group6PlotV3(wfCfg,Vmat,Imat,dat_file,currentFolder,i) warning off MATLAB:print:UIControlsScaled %surpresses resizing warning set(figMMA,'PaperUnits','inches','PaperPosition',[0 0 17 11]); print(figMMA,plotFilePath1,'-dpng'); + sb.g6PlotFilePath = plotFilePath1; % log NLTimage dTxt = split(plotFilePath1,"\"); nltIm.DisplayText = dTxt(end); @@ -518,6 +531,7 @@ function group6PlotV3(wfCfg,Vmat,Imat,dat_file,currentFolder,i) warning off MATLAB:print:UIControlsScaled set(figVector,'PaperUnits','inches','PaperPosition',[0 0 17 11]); print(figVector,plotFilePathVec,'-dpng','-r72'); + sb.g1PlotFilePath = plotFilePathVec; dTxt = split(plotFilePathVec,"\"); nltIm.DisplayText = dTxt(end); nltIm.Group = 1; diff --git a/toGPA_G1_G6_MinMaxVectorPlots/MIT_license.txt b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/MIT_license.txt similarity index 100% rename from toGPA_G1_G6_MinMaxVectorPlots/MIT_license.txt rename to Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/MIT_license.txt diff --git a/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/SnC_G1_G6_MinMaxVectorPlots.prj b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/SnC_G1_G6_MinMaxVectorPlots.prj new file mode 100644 index 0000000..8ea1b20 --- /dev/null +++ b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/SnC_G1_G6_MinMaxVectorPlots.prj @@ -0,0 +1,139 @@ + + + SnC_G1_G6_MinMaxVectorPlots + + + 1.0 + + + + + + + + \SnC_G1_G6_MinMaxVectorPlots\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\SnC_G1_G6_MinMaxVectorPlots\for_testing + ${PROJECT_ROOT}\SnC_G1_G6_MinMaxVectorPlots\for_redistribution_files_only + ${PROJECT_ROOT}\SnC_G1_G6_MinMaxVectorPlots\for_redistribution + ${PROJECT_ROOT}\SnC_G1_G6_MinMaxVectorPlots + false + + subtarget.net.component + + SnC_G1_G6_MinMaxVectorPlots + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + SnC_G1_G6_MinMaxVectorPlots + Analytic + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G1_G6_MinMaxVectorPlots + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\AustinG1G6.m + + + + + ${PROJECT_ROOT}\AustinG1G6.m + + + + + + + + + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G1_G6_MinMaxVectorPlots\SnC_G1_G6_MinMaxVectorPlots\for_testing\SnC_G1_G6_MinMaxVectorPlots.dll + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G1_G6_MinMaxVectorPlots\SnC_G1_G6_MinMaxVectorPlots\for_testing\SnC_G1_G6_MinMaxVectorPlots_overview.html + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G1_G6_MinMaxVectorPlots\SnC_G1_G6_MinMaxVectorPlots\for_testing\SnC_G1_G6_MinMaxVectorPlotsNative.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/toGPA_G1_G6_MinMaxVectorPlots/groupVoltCurr.m b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/groupVoltCurr.m similarity index 100% rename from toGPA_G1_G6_MinMaxVectorPlots/groupVoltCurr.m rename to Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/groupVoltCurr.m diff --git a/toGPA_G1_G6_MinMaxVectorPlots/readCFG_COMTRADE.m b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/readCFG_COMTRADE.m similarity index 100% rename from toGPA_G1_G6_MinMaxVectorPlots/readCFG_COMTRADE.m rename to Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/readCFG_COMTRADE.m diff --git a/toGPA_G1_G6_MinMaxVectorPlots/readDAT_COMTRADE.m b/Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/readDAT_COMTRADE.m similarity index 100% rename from toGPA_G1_G6_MinMaxVectorPlots/readDAT_COMTRADE.m rename to Intellirupters/toGPA_G1_G6_MinMaxVectorPlots/readDAT_COMTRADE.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/Austin_G2_RideThrough.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/Austin_G2_RideThrough.m similarity index 90% rename from toGPA_G2_IEEE 1668 Ridethrough/Austin_G2_RideThrough.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/Austin_G2_RideThrough.m index e9db1c2..088ef63 100644 --- a/toGPA_G2_IEEE 1668 Ridethrough/Austin_G2_RideThrough.m +++ b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/Austin_G2_RideThrough.m @@ -1,37 +1,47 @@ -clc -clear all - -currentFolder = pwd; -folderPath = horzcat(currentFolder,'\Input') -D = genpath(folderPath); -fileFolders = split(D,';'); -max = size(fileFolders); -max = max(1,1); -i = 0; -for i = 2:max - fileFolders{i,1}; - currentfile = string(fileFolders{i,1}); - S = strcat(currentfile,'\','*.DAT'); - - files = dir(S); - for file = files' - the_size = file.bytes; - if the_size > 10000 - GBB_local = importGBBlistFile150(horzcat(currentFolder,'\classification.txt')); - GBB_local = table2struct(GBB_local); - dat_file = strcat(currentfile,'\',file.name); - dat_file = char(dat_file); - cfg_file = strcat(dat_file(1:end-3),'CFG'); - waveFormCfg = readCFG_COMTRADE(cfg_file); - waveFormDat = readDAT_COMTRADE(dat_file,waveFormCfg); - [Imat,Vmat,~,~] = groupVoltCurr(waveFormDat.analog); - ccPlotRideThroughV4(waveFormCfg,Vmat,Imat,GBB_local,dat_file,i,currentFolder) - i = i + 1 - end +function tags = ccPlotRideThroughV4Analytic(Voltage, Current, Fs, Setting) + tags = []; + if ~Setting.ExecuteAnalytic + return end -end - + Vmat = []; + Imat = []; + Vmat = cat(1, Vmat, Voltage(:,1)'); % VX1 + Vmat = cat(1, Vmat, Voltage(:,2)'); % VX2 + Vmat = cat(1, Vmat, Voltage(:,3)'); % VX3 + Vmat = cat(1, Vmat, Voltage(:,4)'); % VY1 + Vmat = cat(1, Vmat, Voltage(:,5)'); % VY2 + Vmat = cat(1, Vmat, Voltage(:,6)'); % VY3 + Imat = cat(1, Imat, Current(:,1)'); % I1 + Imat = cat(1, Imat, Current(:,2)'); % I2 + Imat = cat(1, Imat, Current(:,3)'); % I3 + + classificationsPath = convertStringsToChars(Setting.ClassificationsPath); + GBB_local = importGBBlistFile150(classificationsPath); + GBB_local = table2struct(GBB_local); + + cfg = struct; + cfg.station_name = convertStringsToChars(Setting.Station); + cfg.recording_device = convertStringsToChars(Setting.Device); + cfg.lf = Setting.SystemFrequency; + cfg.samp = Fs; + cfg.endsamp = Setting.SampleCount; + cfg.startdate = convertStringsToChars(Setting.EventDate); + cfg.starttime = convertStringsToChars(Setting.EventTime); + + dat_file = convertStringsToChars(Setting.InputFilename); + outputFolder = convertStringsToChars(Setting.OutputFolder); + + result = ccPlotRideThroughV4(cfg, Vmat, Imat, GBB_local, dat_file, 0, outputFolder); + + if isfield(result, 'plotFilePath') + tag = struct; + tag.Name = 'G2 IEEE 1668 Ridethrough Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.plotFilePath; + tags = [tags, tag]; + end +end function sendBack = ccPlotRideThroughV4(wfCfg,Vmat,Imat,gbb,dat_file,i,currentFolder) @@ -469,6 +479,7 @@ function sendBack = ccPlotRideThroughV4(wfCfg,Vmat,Imat,gbb,dat_file,i,currentFo warning off MATLAB:print:UIControlsScaled %surpresses resizing warning set(fig1668,'PaperUnits','inches','PaperPosition',[0 0 17 11]); print(fig1668, rtPathFile,'-dpng',plotResolution); % for pdf work space + sendBack.plotFilePath = rtPathFile; fclose('all'); close(fig1668); diff --git a/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/SnC_G2_IEEE_1668_Ridethrough.prj b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/SnC_G2_IEEE_1668_Ridethrough.prj new file mode 100644 index 0000000..cc18531 --- /dev/null +++ b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/SnC_G2_IEEE_1668_Ridethrough.prj @@ -0,0 +1,148 @@ + + + SnC_G2_IEEE_1668_Ridethrough + + + 1.0 + + + + + + + + \SnC_G2_IEEE_1668_Ridethrough\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\SnC_G2_IEEE_1668_Ridethrough\for_testing + ${PROJECT_ROOT}\SnC_G2_IEEE_1668_Ridethrough\for_redistribution_files_only + ${PROJECT_ROOT}\SnC_G2_IEEE_1668_Ridethrough\for_redistribution + ${PROJECT_ROOT}\SnC_G2_IEEE_1668_Ridethrough + false + + subtarget.net.component + + SnC_G2_IEEE_1668_Ridethrough + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + SnC_G2_IEEE_1668_Ridethrough + Analytic + + C:\Projects\epb-matlab\Intellirupters\toGPA_G2_IEEE 1668 Ridethrough + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\Austin_G2_RideThrough.m + + + + + ${PROJECT_ROOT}\Austin_G2_RideThrough.m + + + + + + ${PROJECT_ROOT}\ccClassifyV2.m + ${PROJECT_ROOT}\ccCullPoints.m + ${PROJECT_ROOT}\ccSampleStartEndDuration.m + ${PROJECT_ROOT}\ccStructDefaults.m + ${PROJECT_ROOT}\ccVectorDefinitionsV3.m + ${PROJECT_ROOT}\ccVectorPQmatrixVI.m + ${PROJECT_ROOT}\importGBBlistFile150.m + ${PROJECT_ROOT}\plotResizeAxesTight.m + + + + + + C:\Projects\epb-matlab\Intellirupters\toGPA_G2_IEEE 1668 Ridethrough\SnC_G2_IEEE_1668_Ridethrough\for_testing\SnC_G2_IEEE_1668_RidethroughNative.dll + C:\Projects\epb-matlab\Intellirupters\toGPA_G2_IEEE 1668 Ridethrough\SnC_G2_IEEE_1668_Ridethrough\for_testing\SnC_G2_IEEE_1668_Ridethrough_overview.html + C:\Projects\epb-matlab\Intellirupters\toGPA_G2_IEEE 1668 Ridethrough\SnC_G2_IEEE_1668_Ridethrough\for_testing\SnC_G2_IEEE_1668_Ridethrough.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/toGPA_G2_IEEE 1668 Ridethrough/ccClassifyV2.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccClassifyV2.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/ccClassifyV2.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccClassifyV2.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/ccCullPoints.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccCullPoints.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/ccCullPoints.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccCullPoints.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/ccSampleStartEndDuration.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccSampleStartEndDuration.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/ccSampleStartEndDuration.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccSampleStartEndDuration.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/ccStructDefaults.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccStructDefaults.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/ccStructDefaults.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccStructDefaults.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/ccVectorDefinitionsV3.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccVectorDefinitionsV3.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/ccVectorDefinitionsV3.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccVectorDefinitionsV3.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/ccVectorPQmatrixVI.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccVectorPQmatrixVI.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/ccVectorPQmatrixVI.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/ccVectorPQmatrixVI.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/classification.txt b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/classification.txt similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/classification.txt rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/classification.txt diff --git a/toGPA_G2_IEEE 1668 Ridethrough/groupVoltCurr.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/groupVoltCurr.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/groupVoltCurr.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/groupVoltCurr.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/importGBBlistFile150.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/importGBBlistFile150.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/importGBBlistFile150.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/importGBBlistFile150.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/plotResizeAxesTight.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/plotResizeAxesTight.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/plotResizeAxesTight.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/plotResizeAxesTight.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/readCFG_COMTRADE.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/readCFG_COMTRADE.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/readCFG_COMTRADE.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/readCFG_COMTRADE.m diff --git a/toGPA_G2_IEEE 1668 Ridethrough/readDAT_COMTRADE.m b/Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/readDAT_COMTRADE.m similarity index 100% rename from toGPA_G2_IEEE 1668 Ridethrough/readDAT_COMTRADE.m rename to Intellirupters/toGPA_G2_IEEE 1668 Ridethrough/readDAT_COMTRADE.m diff --git a/toGPA_G3_FuseTCCcurve/AustinG3.m b/Intellirupters/toGPA_G3_FuseTCCcurve/AustinG3.m similarity index 83% rename from toGPA_G3_FuseTCCcurve/AustinG3.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/AustinG3.m index 039d6f1..a51cb9f 100644 --- a/toGPA_G3_FuseTCCcurve/AustinG3.m +++ b/Intellirupters/toGPA_G3_FuseTCCcurve/AustinG3.m @@ -1,33 +1,45 @@ -clc -clear all - -currentFolder = pwd; -folderPath = horzcat(currentFolder,'\Input') -D = genpath(folderPath); -fileFolders = split(D,';'); -max = size(fileFolders); -max = max(1,1); -i = 0; -for i = 2:max - fileFolders{i,1}; - currentfile = string(fileFolders{i,1}); - S = strcat(currentfile,'\','*.DAT'); - - files = dir(S); - for file = files' - the_size = file.bytes; - if the_size > 10000 - GBB_local = importGBBlistFile150(horzcat(currentFolder,'\classification.txt')); - GBB_local = table2struct(GBB_local); - dat_file = strcat(currentfile,'\',file.name); - dat_file = char(dat_file); - cfg_file = strcat(dat_file(1:end-3),'CFG'); - waveFormCfg = readCFG_COMTRADE(cfg_file); - waveFormDat = readDAT_COMTRADE(dat_file,waveFormCfg); - [Imat,Vmat,~,~] = groupVoltCurr(waveFormDat.analog); - ccPlotFuseTCC(waveFormCfg,waveFormDat,Vmat,Imat,GBB_local,currentFolder,dat_file,i) - i = i + 1 - end +function tags = ccPlotFuseTCCAnalytic(Voltage, Current, Fs, Setting) + tags = []; + if ~Setting.ExecuteAnalytic + return + end + + Vmat = []; + Imat = []; + Vmat = cat(1, Vmat, Voltage(:,1)'); % VX1 + Vmat = cat(1, Vmat, Voltage(:,2)'); % VX2 + Vmat = cat(1, Vmat, Voltage(:,3)'); % VX3 + Vmat = cat(1, Vmat, Voltage(:,4)'); % VY1 + Vmat = cat(1, Vmat, Voltage(:,5)'); % VY2 + Vmat = cat(1, Vmat, Voltage(:,6)'); % VY3 + Imat = cat(1, Imat, Current(:,1)'); % I1 + Imat = cat(1, Imat, Current(:,2)'); % I2 + Imat = cat(1, Imat, Current(:,3)'); % I3 + + classificationsPath = convertStringsToChars(Setting.ClassificationsPath); + GBB_local = importGBBlistFile150(classificationsPath); + GBB_local = table2struct(GBB_local); + + cfg = struct; + cfg.station_name = convertStringsToChars(Setting.Station); + cfg.recording_device = convertStringsToChars(Setting.Device); + cfg.lf = Setting.SystemFrequency; + cfg.samp = Fs; + cfg.endsamp = Setting.SampleCount; + cfg.startdate = convertStringsToChars(Setting.EventDate); + cfg.starttime = convertStringsToChars(Setting.EventTime); + + dat_file = convertStringsToChars(Setting.InputFilename); + outputFolder = convertStringsToChars(Setting.OutputFolder); + + result = ccPlotFuseTCC(cfg, [], Vmat, Imat, GBB_local, outputFolder, dat_file, 0); + + if isfield(result, 'plotFilePath') + tag = struct; + tag.Name = 'G3 Suspected Blown Fuse Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.plotFilePath; + tags = [tags, tag]; end end @@ -253,6 +265,7 @@ function sendBack = ccPlotFuseTCC(dataCFG,dataDAT,Vmatrix,Imatrix,GBB_local,curr warning off MATLAB:print:UIControlsScaled %surpresses resizing warning set(figFuse,'PaperUnits','inches','PaperPosition',[0 0 17 11]); print(figFuse, plotPathFile,'-dpng'); %rwh + sendBack.plotFilePath = plotPathFile; dTxt = split(plotPathFile,"\"); nltIm.DisplayText = dTxt(end); nltIm.Group = 3; diff --git a/toGPA_G3_FuseTCCcurve/NBmodel.mat b/Intellirupters/toGPA_G3_FuseTCCcurve/NBmodel.mat similarity index 100% rename from toGPA_G3_FuseTCCcurve/NBmodel.mat rename to Intellirupters/toGPA_G3_FuseTCCcurve/NBmodel.mat diff --git a/toGPA_G3_FuseTCCcurve/NaiveBayesCl_v2.m b/Intellirupters/toGPA_G3_FuseTCCcurve/NaiveBayesCl_v2.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/NaiveBayesCl_v2.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/NaiveBayesCl_v2.m diff --git a/Intellirupters/toGPA_G3_FuseTCCcurve/SnC_G3_FuseTCCcurve.prj b/Intellirupters/toGPA_G3_FuseTCCcurve/SnC_G3_FuseTCCcurve.prj new file mode 100644 index 0000000..95b9513 --- /dev/null +++ b/Intellirupters/toGPA_G3_FuseTCCcurve/SnC_G3_FuseTCCcurve.prj @@ -0,0 +1,150 @@ + + + SnC_G3_FuseTCCcurve + + + 1.0 + + + + + + + + \SnC_G3_FuseTCCcurve\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\SnC_G3_FuseTCCcurve\for_testing + ${PROJECT_ROOT}\SnC_G3_FuseTCCcurve\for_redistribution_files_only + ${PROJECT_ROOT}\SnC_G3_FuseTCCcurve\for_redistribution + ${PROJECT_ROOT}\SnC_G3_FuseTCCcurve + false + + subtarget.net.component + + SnC_G3_FuseTCCcurve + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + SnC_G3_FuseTCCcurve + Analytic + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G3_FuseTCCcurve + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\AustinG3.m + + + + + ${PROJECT_ROOT}\AustinG3.m + + + + + + ${PROJECT_ROOT}\ccClassifyV2.m + ${PROJECT_ROOT}\ccGetTCC.m + ${PROJECT_ROOT}\ccPlotFileNameFormatV2.m + ${PROJECT_ROOT}\endSampleHilbert.m + ${PROJECT_ROOT}\getFuseSize.m + ${PROJECT_ROOT}\getNumEvents.m + ${PROJECT_ROOT}\importGBBlistFile150.m + ${PROJECT_ROOT}\NaiveBayesCl_v2.m + ${PROJECT_ROOT}\NBmodel.mat + ${PROJECT_ROOT}\plotResizeAxesTight.m + + + + + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G3_FuseTCCcurve\SnC_G3_FuseTCCcurve\for_testing\SnC_G3_FuseTCCcurveNative.dll + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G3_FuseTCCcurve\SnC_G3_FuseTCCcurve\for_testing\SnC_G3_FuseTCCcurve_overview.html + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G3_FuseTCCcurve\SnC_G3_FuseTCCcurve\for_testing\SnC_G3_FuseTCCcurve.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/toGPA_G3_FuseTCCcurve/ccClassifyV2.m b/Intellirupters/toGPA_G3_FuseTCCcurve/ccClassifyV2.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/ccClassifyV2.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/ccClassifyV2.m diff --git a/toGPA_G3_FuseTCCcurve/ccGetTCC.m b/Intellirupters/toGPA_G3_FuseTCCcurve/ccGetTCC.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/ccGetTCC.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/ccGetTCC.m diff --git a/toGPA_G3_FuseTCCcurve/ccLogTextBox.m b/Intellirupters/toGPA_G3_FuseTCCcurve/ccLogTextBox.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/ccLogTextBox.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/ccLogTextBox.m diff --git a/toGPA_G3_FuseTCCcurve/ccPlotFileNameFormatV2.m b/Intellirupters/toGPA_G3_FuseTCCcurve/ccPlotFileNameFormatV2.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/ccPlotFileNameFormatV2.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/ccPlotFileNameFormatV2.m diff --git a/toGPA_G3_FuseTCCcurve/ccStructDefaults.m b/Intellirupters/toGPA_G3_FuseTCCcurve/ccStructDefaults.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/ccStructDefaults.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/ccStructDefaults.m diff --git a/toGPA_G3_FuseTCCcurve/classification.txt b/Intellirupters/toGPA_G3_FuseTCCcurve/classification.txt similarity index 100% rename from toGPA_G3_FuseTCCcurve/classification.txt rename to Intellirupters/toGPA_G3_FuseTCCcurve/classification.txt diff --git a/toGPA_G3_FuseTCCcurve/endSampleHilbert.m b/Intellirupters/toGPA_G3_FuseTCCcurve/endSampleHilbert.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/endSampleHilbert.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/endSampleHilbert.m diff --git a/toGPA_G3_FuseTCCcurve/getFuseSize.m b/Intellirupters/toGPA_G3_FuseTCCcurve/getFuseSize.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/getFuseSize.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/getFuseSize.m diff --git a/toGPA_G3_FuseTCCcurve/getNumEvents.m b/Intellirupters/toGPA_G3_FuseTCCcurve/getNumEvents.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/getNumEvents.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/getNumEvents.m diff --git a/toGPA_G3_FuseTCCcurve/groupVoltCurr.m b/Intellirupters/toGPA_G3_FuseTCCcurve/groupVoltCurr.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/groupVoltCurr.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/groupVoltCurr.m diff --git a/toGPA_G3_FuseTCCcurve/importGBBlistFile150.m b/Intellirupters/toGPA_G3_FuseTCCcurve/importGBBlistFile150.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/importGBBlistFile150.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/importGBBlistFile150.m diff --git a/toGPA_G3_FuseTCCcurve/plotResizeAxesTight.m b/Intellirupters/toGPA_G3_FuseTCCcurve/plotResizeAxesTight.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/plotResizeAxesTight.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/plotResizeAxesTight.m diff --git a/toGPA_G3_FuseTCCcurve/readCFG_COMTRADE.m b/Intellirupters/toGPA_G3_FuseTCCcurve/readCFG_COMTRADE.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/readCFG_COMTRADE.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/readCFG_COMTRADE.m diff --git a/toGPA_G3_FuseTCCcurve/readDAT_COMTRADE.m b/Intellirupters/toGPA_G3_FuseTCCcurve/readDAT_COMTRADE.m similarity index 100% rename from toGPA_G3_FuseTCCcurve/readDAT_COMTRADE.m rename to Intellirupters/toGPA_G3_FuseTCCcurve/readDAT_COMTRADE.m diff --git a/toGPA_G5_Harmonics/AFC.csv b/Intellirupters/toGPA_G5_Harmonics/AFC.csv similarity index 100% rename from toGPA_G5_Harmonics/AFC.csv rename to Intellirupters/toGPA_G5_Harmonics/AFC.csv diff --git a/toGPA_G5_Harmonics/AustinG5_Harmonics.m b/Intellirupters/toGPA_G5_Harmonics/AustinG5_Harmonics.m similarity index 96% rename from toGPA_G5_Harmonics/AustinG5_Harmonics.m rename to Intellirupters/toGPA_G5_Harmonics/AustinG5_Harmonics.m index 868f582..01015ed 100644 --- a/toGPA_G5_Harmonics/AustinG5_Harmonics.m +++ b/Intellirupters/toGPA_G5_Harmonics/AustinG5_Harmonics.m @@ -1,35 +1,48 @@ -clc -clear all -currentFolder = pwd; -D = genpath('D:\ToGPA\toGPA_G5_Harmonics\Input'); -fileFolders = split(D,';'); -max = size(fileFolders); -max = max(1,1); -i = 0; -for i = 2:max - fileFolders{i,1}; - currentfile = string(fileFolders{i,1}); - S = strcat(currentfile,'\','*.DAT'); - - files = dir(S); - for file = files' - the_size = file.bytes; - if the_size > 10000 - GBB_local = importGBBlistFile150SubFunction('D:\ToGPA\toGPA_G5_Harmonics\classification.txt'); - GBB_local = table2struct(GBB_local); - dat_file = strcat(currentfile,'\',file.name); - dat_file = char(dat_file); - cfg_file = strcat(dat_file(1:end-3),'CFG'); - waveFormCfg = readCFG_COMTRADE(cfg_file); - waveFormDat = readDAT_COMTRADE(dat_file,waveFormCfg); - [Imat,Vmat,~,~] = groupVoltCurr(waveFormDat.analog); - group5Harmonics(waveFormCfg,Vmat,Imat,GBB_local,dat_file,i,currentFolder) - i = i + 1; - end +function tags = group5HarmonicsAnalytic(Voltage, Current, Fs, Setting) + tags = []; + if ~Setting.ExecuteAnalytic + return + end + + Vmat = []; + Imat = []; + Vmat = cat(1, Vmat, Voltage(:,1)'); % VX1 + Vmat = cat(1, Vmat, Voltage(:,2)'); % VX2 + Vmat = cat(1, Vmat, Voltage(:,3)'); % VX3 + Vmat = cat(1, Vmat, Voltage(:,4)'); % VY1 + Vmat = cat(1, Vmat, Voltage(:,5)'); % VY2 + Vmat = cat(1, Vmat, Voltage(:,6)'); % VY3 + Imat = cat(1, Imat, Current(:,1)'); % I1 + Imat = cat(1, Imat, Current(:,2)'); % I2 + Imat = cat(1, Imat, Current(:,3)'); % I3 + + classificationsPath = convertStringsToChars(Setting.ClassificationsPath); + GBB_local = importGBBlistFile150SubFunction(classificationsPath); + GBB_local = table2struct(GBB_local); + + cfg = struct; + cfg.station_name = convertStringsToChars(Setting.Station); + cfg.recording_device = convertStringsToChars(Setting.Device); + cfg.lf = Setting.SystemFrequency; + cfg.samp = Fs; + cfg.endsamp = Setting.SampleCount; + cfg.startdate = convertStringsToChars(Setting.EventDate); + cfg.starttime = convertStringsToChars(Setting.EventTime); + + dat_file = convertStringsToChars(Setting.InputFilename); + outputFolder = convertStringsToChars(Setting.OutputFolder); + + result = group5Harmonics(cfg, Vmat, Imat, GBB_local, dat_file, 0, outputFolder); + + if isfield(result, 'plotFilePath') + tag = struct; + tag.Name = 'G5 Harmonics Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.plotFilePath; + tags = [tags, tag]; end end - function sendBack = group5Harmonics(wfCfg,Vmat,Imat,GBBv2s,dat_file,i,currentFolder) try Circuit_Phase_Orientation = split(wfCfg.station_name,'.') @@ -646,15 +659,15 @@ function sendBack = group5Harmonics(wfCfg,Vmat,Imat,GBBv2s,dat_file,i,currentFol replaceGBBID = strcat(replaceGBBID,',',char(checkGBBID508.gbbID)); allGBBID = [allGBBID string(checkGBBID508.gbbID)]; end - if ~isempty(replaceGBBID) - gbbID = replaceGBBID(2:end); - else - setTo = 'yes'; %? - setOther = '---'; - GBBv2s = ccClassifyV2SubFunction(GBBv2s,gbbID,'group5',setTo,setOther,'updateOne'); + % if ~isempty(replaceGBBID) + % gbbID = replaceGBBID(2:end); + % else + % setTo = 'yes'; %? + % setOther = '---'; + % GBBv2s = ccClassifyV2SubFunction(GBBv2s,gbbID,'group5',setTo,setOther,'updateOne'); - allGBBID = string(gbbID); - end + % allGBBID = string(gbbID); + % end @@ -1162,11 +1175,12 @@ function sendBack = group5Harmonics(wfCfg,Vmat,Imat,GBBv2s,dat_file,i,currentFol warning off MATLAB:print:UIControlsScaled %surpresses resizing warning set(figG5,'PaperUnits','inches','PaperPosition',[0 0 17 11]); - currentFolder = pwd; + %currentFolder = pwd; plotPathFile = [currentFolder,'\Output\',plotFileName1]; print(figG5, plotPathFile,'-dpng') %errors here + sendBack.plotFilePath = plotPathFile; for i = 1:length(allGBBID) GBBv2s = ccClassifyV2SubFunction(GBBv2s,allGBBID(i),'ignore','ignore',plotPathFile,'savePlotName'); diff --git a/Intellirupters/toGPA_G5_Harmonics/SnC_G5_Harmonics.prj b/Intellirupters/toGPA_G5_Harmonics/SnC_G5_Harmonics.prj new file mode 100644 index 0000000..c21c288 --- /dev/null +++ b/Intellirupters/toGPA_G5_Harmonics/SnC_G5_Harmonics.prj @@ -0,0 +1,148 @@ + + + SnC_G5_Harmonics + + + 1.0 + + + + + + + + \SnC_G5_Harmonics\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\SnC_G5_Harmonics\for_testing + ${PROJECT_ROOT}\SnC_G5_Harmonics\for_redistribution_files_only + ${PROJECT_ROOT}\SnC_G5_Harmonics\for_redistribution + ${PROJECT_ROOT}\SnC_G5_Harmonics + false + + subtarget.net.component + + SnC_G5_Harmonics + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + SnC_G5_Harmonics + Analytic + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G5_Harmonics + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\AustinG5_Harmonics.m + + + + + ${PROJECT_ROOT}\AustinG5_Harmonics.m + + + + + + ${PROJECT_ROOT}\AFC.csv + ${PROJECT_ROOT}\ccVectorDefinitions.m + ${PROJECT_ROOT}\ccVectorDefinitionsV3.m + ${PROJECT_ROOT}\ccVectorPQmatrixVI.m + ${PROJECT_ROOT}\harmonicCheck_v5.m + ${PROJECT_ROOT}\plotResizeAxesTight.m + ${PROJECT_ROOT}\searchFor503.m + ${PROJECT_ROOT}\searchFor507or508.m + + + + + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G5_Harmonics\SnC_G5_Harmonics\for_testing\SnC_G5_Harmonics_overview.html + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G5_Harmonics\SnC_G5_Harmonics\for_testing\SnC_G5_HarmonicsNative.dll + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G5_Harmonics\SnC_G5_Harmonics\for_testing\SnC_G5_Harmonics.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/toGPA_G5_Harmonics/ccVectorDefinitions.m b/Intellirupters/toGPA_G5_Harmonics/ccVectorDefinitions.m similarity index 100% rename from toGPA_G5_Harmonics/ccVectorDefinitions.m rename to Intellirupters/toGPA_G5_Harmonics/ccVectorDefinitions.m diff --git a/toGPA_G5_Harmonics/ccVectorDefinitionsV3.m b/Intellirupters/toGPA_G5_Harmonics/ccVectorDefinitionsV3.m similarity index 100% rename from toGPA_G5_Harmonics/ccVectorDefinitionsV3.m rename to Intellirupters/toGPA_G5_Harmonics/ccVectorDefinitionsV3.m diff --git a/toGPA_G5_Harmonics/ccVectorPQmatrixVI.m b/Intellirupters/toGPA_G5_Harmonics/ccVectorPQmatrixVI.m similarity index 100% rename from toGPA_G5_Harmonics/ccVectorPQmatrixVI.m rename to Intellirupters/toGPA_G5_Harmonics/ccVectorPQmatrixVI.m diff --git a/toGPA_G5_Harmonics/classification.txt b/Intellirupters/toGPA_G5_Harmonics/classification.txt similarity index 100% rename from toGPA_G5_Harmonics/classification.txt rename to Intellirupters/toGPA_G5_Harmonics/classification.txt diff --git a/toGPA_G5_Harmonics/groupVoltCurr.m b/Intellirupters/toGPA_G5_Harmonics/groupVoltCurr.m similarity index 100% rename from toGPA_G5_Harmonics/groupVoltCurr.m rename to Intellirupters/toGPA_G5_Harmonics/groupVoltCurr.m diff --git a/toGPA_G5_Harmonics/harmonicCheck_v5.m b/Intellirupters/toGPA_G5_Harmonics/harmonicCheck_v5.m similarity index 100% rename from toGPA_G5_Harmonics/harmonicCheck_v5.m rename to Intellirupters/toGPA_G5_Harmonics/harmonicCheck_v5.m diff --git a/toGPA_G5_Harmonics/plotResizeAxesTight.m b/Intellirupters/toGPA_G5_Harmonics/plotResizeAxesTight.m similarity index 100% rename from toGPA_G5_Harmonics/plotResizeAxesTight.m rename to Intellirupters/toGPA_G5_Harmonics/plotResizeAxesTight.m diff --git a/toGPA_G5_Harmonics/readCFG_COMTRADE.m b/Intellirupters/toGPA_G5_Harmonics/readCFG_COMTRADE.m similarity index 100% rename from toGPA_G5_Harmonics/readCFG_COMTRADE.m rename to Intellirupters/toGPA_G5_Harmonics/readCFG_COMTRADE.m diff --git a/toGPA_G5_Harmonics/readDAT_COMTRADE.m b/Intellirupters/toGPA_G5_Harmonics/readDAT_COMTRADE.m similarity index 100% rename from toGPA_G5_Harmonics/readDAT_COMTRADE.m rename to Intellirupters/toGPA_G5_Harmonics/readDAT_COMTRADE.m diff --git a/toGPA_G5_Harmonics/searchFor503.m b/Intellirupters/toGPA_G5_Harmonics/searchFor503.m similarity index 100% rename from toGPA_G5_Harmonics/searchFor503.m rename to Intellirupters/toGPA_G5_Harmonics/searchFor503.m diff --git a/toGPA_G5_Harmonics/searchFor507or508.m b/Intellirupters/toGPA_G5_Harmonics/searchFor507or508.m similarity index 100% rename from toGPA_G5_Harmonics/searchFor507or508.m rename to Intellirupters/toGPA_G5_Harmonics/searchFor507or508.m diff --git a/Intellirupters/toGPA_G7_Replay/AustinG7.m b/Intellirupters/toGPA_G7_Replay/AustinG7.m new file mode 100644 index 0000000..53644e2 --- /dev/null +++ b/Intellirupters/toGPA_G7_Replay/AustinG7.m @@ -0,0 +1,2081 @@ +function tags = p1_g6stateChangeHistoryV2Analytic(Voltage, Current, Fs, Setting) + tags = []; + if ~Setting.ExecuteAnalytic + return + end + + Vmat = []; + Imat = []; + Vmat = cat(1, Vmat, Voltage(:,1)'); % VX1 + Vmat = cat(1, Vmat, Voltage(:,2)'); % VX2 + Vmat = cat(1, Vmat, Voltage(:,3)'); % VX3 + Vmat = cat(1, Vmat, Voltage(:,4)'); % VY1 + Vmat = cat(1, Vmat, Voltage(:,5)'); % VY2 + Vmat = cat(1, Vmat, Voltage(:,6)'); % VY3 + Imat = cat(1, Imat, Current(:,1)'); % I1 + Imat = cat(1, Imat, Current(:,2)'); % I2 + Imat = cat(1, Imat, Current(:,3)'); % I3 + + classificationsPath = convertStringsToChars(Setting.ClassificationsPath); + GBB_local = importGBBlistFile150SubFunction(classificationsPath); + GBB_local = table2struct(GBB_local); + + cfg = struct; + cfg.station_name = convertStringsToChars(Setting.Station); + cfg.recording_device = convertStringsToChars(Setting.Device); + cfg.lf = Setting.SystemFrequency; + cfg.samp = Fs; + cfg.endsamp = Setting.SampleCount; + cfg.startdate = convertStringsToChars(Setting.EventDate); + cfg.starttime = convertStringsToChars(Setting.EventTime); + cfg.eventID = Setting.Event_ID; + cfg.soeID = Setting.SOE_ID; + cfg.soeTime = Setting.SOE_Time; + cfg.incidentID = Setting.Incident_ID; + + dat_file = convertStringsToChars(Setting.InputFilename); + outputFolder = convertStringsToChars(Setting.OutputFolder); + + global currentFolder + currentFolder = outputFolder + result = p1_g6stateChangeHistoryV2(cfg, Vmat, Imat, dat_file, 0, outputFolder); + + if isfield(result, 'plotFilePath') + tag = struct; + tag.Name = 'G7 State Change Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.plotFilePath; + tags = [tags, tag]; + end +end + +function sb = p1_g6stateChangeHistoryV2(wfCfg,Vmatrix,Imatrix,dat_file,i,currentFolder) + + try + Circuit_Phase_Orientation = split(wfCfg.station_name,'.') + Circuit = Circuit_Phase_Orientation(1,:) + Circuit_Alt = split(Circuit(1,1),'-') + Phase_Orientation = split(Circuit_Phase_Orientation(2,:),'-'); + Phase = Phase_Orientation(1,:); + Orientation = Phase_Orientation(2,:); + catch + Circuit_Phase_Orientation = split(wfCfg.station_name,'-') + Circuit = Circuit_Phase_Orientation(1,:) + Circuit_Alt = split(Circuit(1,1),'-') + Phase_Orientation = split(Circuit_Phase_Orientation(2,:),'-'); + Phase = Phase_Orientation(1,:); + Orientation = Circuit_Phase_Orientation(3,:); + + end + + + Vmatrix = OrientationCheck(Vmatrix, Orientation); %if YX, rearrange Vmatrix + + newTime = split(dat_file,'.'); + newTime = char(newTime(2,:)); + if strlength(Circuit_Phase_Orientation(1,1)) < 7 + plotFileName1 = append(wfCfg.station_name(1:6),'-',wfCfg.recording_device,'_','G7','_',newTime,'_',int2str(i)); + forPNG = append(wfCfg.station_name(1:6),'-',wfCfg.recording_device); + else + plotFileName1 = append(wfCfg.station_name(1:6),'-',wfCfg.recording_device,wfCfg.station_name(7:13),'_','G7','_',newTime,'_',int2str(i)); + forPNG = append(wfCfg.station_name(1:6),'-',wfCfg.recording_device,wfCfg.station_name(7:13)); + end + + sb = struct; % sb abbreviation for sendBack + valsIn = struct; + refPickup = 700; % To calculate percent of pickup + gbbID = 'GBB621'; + updateBy = 'p1_g6stateChangeHistory'; + setOther = 'no changes - skip waveform'; + sb.skipNote = 'none'; % lame way to begin documenting waveforms not processed + + sensorConfig = 'V123-I123-V456'; + % Note: future development may support these additional configurations + %sensorConfigListAllOptions = 'V123-I123-V456-i456-iPgn-iAgn'; % depricate, superceded by sensor.Config + + % initialize here instead of ccStructDefaults + + sb.default = 'set'; + sb.gbbID = gbbID; + sb.sensorConfig = sensorConfig; + %sb.sensorConfigsSupported = sensorConfigListAllOptions; + sb.changeLimit = 5; % forces or limits measured data points + sb.linVsMeanDiffLimit = 10; % Alert if change points differ significantly + sb.linVsMeanAlert = false; % Alert flag for alarm log (developer review) + + % Waveform cases: only one should be true + sb.disturbance = false; % disturbance event detected + sb.protection = false; % protection event detected + sb.switching = false; % switching operation detected + sb.serviceRest = false; % TIE close detected + sb.noEvent = false; % no changes detected + + % Sensor cases: (los and noSrc mutually exclusive) + % subscript = sensor numbers + sb.V123yes = setSensorFlagSubFunction(sensorConfig,'V123'); % configured? + sb.V123pq = false; % at least one PQ event detected + sb.V123los = false; % had source, then lost at least once + sb.V123noSrc = false; % no source during entire waveform + sb.v123tktnOffset = 1.35; % center point on normalized plot + sb.v123howThick = 0.025; % +/- center point + sb.V123fitOffset = 4; % zero offset for mean and linear fit + sb.V456yes = setSensorFlagSubFunction(sensorConfig,'V456'); % configured? + sb.V456pq = false; % at least one PQ event detected + sb.V456los = false; % had source, then lost at least once + sb.V456noSrc = false; % no source during entire waveform + sb.v456tktnOffset = 1.35; % center point on normalized plot + sb.v456howThick = 0.025; % +/- center point + sb.V456fitOffset = 0; % zero offset for mean and linear fit + sb.I123yes = setSensorFlagSubFunction(sensorConfig,'I123'); % configured? + sb.I123fault = false; % fault flag set by logic + sb.I123logImag = true; % true = i magnitude, false = log normalized i + sb.I123tktnOffset = 1.35; % center point on normalized plot, y axis + sb.I123howThick = 0.025; % +/- center point + sb.I123fitOffset = 2; % zero offset for mean and linear fit + sb.VAyes = false; % Plot changes in power (but nothing logged) + % TODO future support + sb.iPgnyes = setSensorFlagSubFunction(sensorConfig,'iPgn'); % configured? + sb.iPgnfault = false; % pref ground and/or neutral sensor + sb.I456yes = setSensorFlagSubFunction(sensorConfig,'I456'); % configured? + sb.I456fault = false; % fault detection alternate + sb.iAgnyes = setSensorFlagSubFunction(sensorConfig,'iAgn'); % configured? + sb.iAgnfault = false; % Alternate ground and/or neutral sensor + + % where is the disturbance relative to me + sb.distUp = false; % distrurbance upstream + sb.distTrip = false; % disturbance cleared by me (this waveform) + sb.distDown = false; % downstream protection event + + % since this is historical, minimum durations filter noise + sb.faultMin = 0.25; % cycles (code converts to samples based on sample frequency) + sb.pqMin = 3; % cycles (code works in samples) + + % since this is historical, tighter PQ to filter minor PQ events + sb.pqMaxPU = 0.75; % allowable sag (PU normalized by peak swell!) + sb.pqMinPU = 0.20; % ignore LOS cases + + % Figure parameters + sb.figSize = [0 0 1 1]; + sb.p1space = [0.05 0.66 0.6 0.3]; % plot 1 space + sb.p2space = [0.05 0.33 0.6 0.3]; % plot 2 space + sb.p3space = [0.05 0 0.6 0.3]; % plot 3 space + sb.p4space = [0.65 0.66 0.3 0.3]; % plot 4 space + sb.p5space = [0.65 0.33 0.3 0.3]; % plot 5 space + sb.fontSz = 0.035; % size of text + + % TODO: compare methods + %sb.histLogicVsRudy = false; % true if both approaches detect switching + %sb.chgPtsMeanVsLinear = false; % analyze differences between mean and linear + + + + % New logic - determine voltage sensor change points + vsRef = p1_voltSensorReferenceSubFunction(wfCfg,Vmatrix,Imatrix); + if vsRef.changes == 0 + % Alternative concept is to force a change at midpoint + + return; % Abort processing waveform if no changes + end + vsRef.chPts = vsRef.chPts'; % transpose so changes and mx are each a single row + logMe = strcat(" Changes detected: ",num2str(vsRef.changes)); + disp(logMe); + logMe = strcat(" ---Change points: ",num2str(vsRef.chPts)); + disp(logMe); + + + oa = struct; + minfaultSamp = round(((wfCfg.samp/60) * 600),0) + 1; % integer > 0 + minpqSamp = round(((wfCfg.samp/60) * 3),0) + 1; % integer > 0 + lastN = wfCfg.endsamp; + + plotPathFile = [currentFolder,'\Output\',plotFileName1] + inLog = p1_stateChangeDataLogV2SubFunction('getDefaults','dummy','dummy'); % get structures + outLog = p1_stateChangeDataLogV2SubFunction('setCommonValues',inLog,'dummy',Circuit,Phase,Orientation,wfCfg); % assigns common values + outLog.colValue.PlotFileName = plotPathFile; + logMe_cv = outLog.colValue; % local copy of column values strcture + logMe_cv.PlotFileName = plotPathFile; + logMe_mv1toN = outLog.mv1toN; % local copy of measured values + commonStuff = {'nvPH1';'nvPH2';'nvPH3';'mvUnits';'mvNote';'dydtUnits';'cStateNote'; ... + 'ElectedCycle';'waveformTimeSlot';'XDAreplayID'}; + oa.commonStuff = commonStuff; % pass list down to store values + oa.comtradeDT = [wfCfg.startdate,',',wfCfg.starttime]; + oa.samp = wfCfg.samp; + +% X_startdate = split(wfCfg.startdate,'/'); +% new_startdate = strcat(string(X_startdate(3,1)),"-", string(X_startdate(2,1)),"-",string(X_startdate(1,1))); +% new_starttime = datetime(wfCfg.starttime,'format','HH:mm:ss.SSSSSS','TimeZone','America/New_York') - hours(4); +% if ~isdst(datetime(new_startdate,'TimeZone','America/New_York')) +% new_starttime = new_starttime - hours(1) +% end + + X_startdate = split(wfCfg.startdate,'/'); + new_startdate = strcat(string(X_startdate(3,1)),"-", string(X_startdate(2,1)),"-",string(X_startdate(1,1))); + new_startdate = datetime(new_startdate,'format','uuuu-MM-dd HH:mm:ss.SSS','TimeZone','America/New_York') + new_starttime = datetime(wfCfg.starttime,'format','HH:mm:ss.SSS','TimeZone','America/New_York') + curDateTime = (new_startdate + timeofday(new_starttime)) - hours(4); + + if ~isdst(datetime(curDateTime,'TimeZone','America/New_York')) + curDateTime = curDateTime - hours(1) + end + + date_time = char(datetime(curDateTime,'format','dd/MM/uuuu HH:mm:ss.SSSSSS')) + %date_time = [wfCfg.startdate,' ',char(new_starttime)] + %date_time = [wfCfg.startdate,' ',wfCfg.starttime] + inTss = ccTimeStampSampleV2SubFunction(date_time,'defaultSOElocal'); % needed to get time info + inTss.comtradeDT = oa.comtradeDT; % TODO, unnecessary in V2 + + + + % Vector analysis, waveforms and rms calculations + intoVPQMVI.default = 'getDefaults'; + intoVPQMVI = ccVectorPQmatrixVISubFunction(intoVPQMVI,wfCfg,Vmatrix,Imatrix); + vo = ccVectorPQmatrixVISubFunction(intoVPQMVI,wfCfg,Vmatrix,Imatrix); + spc = vo.spc; % samples per cycle + oa.spc = spc; + + thr_hz60 = 0.800000000000000; + % Determine m1m2 using new voltage reference logic + % Step 1, find mxHere and mxHereTime + % TODO: add case 0 (no changes) - m1 at waveform center + switch vsRef.changes + case 0 + mxHere = round((lastN/2),0); + vsRef.mxHere = mxHere; + mxHereTime = strings(1,1); + inTss.sample = mxHere; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + vsRef.mxHereTime = string(mxTd.CTdateStringEvent); + + case 1 + % One change produces two measurements + % mxHere - x axis point for all sensors + xPointM1 = round((vsRef.chPts/2),0); + xPointM2 = round(((vsRef.chPts + lastN)/2),0) - 1; + mxHere = [xPointM1, xPointM2]; + vsRef.mxHere = mxHere; + mxHereTime = strings(1,2); + inTss.sample = xPointM1; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(1) = string(mxTd.CTdateStringEvent); + inTss.sample = xPointM2; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(2) = string(mxTd.CTdateStringEvent); + vsRef.mxHereTime = mxHereTime; + + case 2 + % Two changes produces three measurements + % mxHere - x axis point for all sensors + xPointM1 = round((vsRef.chPts(1)/2),0); + xPointM2 = round(((vsRef.chPts(1)+vsRef.chPts(2))/2),0); + xPointM3 = round(((vsRef.chPts(2) + lastN)/2),0) - 1; + mxHere = [xPointM1, xPointM2, xPointM3]; + vsRef.mxHere = mxHere; + % mxHereTime - corresponding time at these points + mxHereTime = strings(1,3); + inTss.sample = xPointM1; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(1) = string(mxTd.CTdateStringEvent); + inTss.sample = xPointM2; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(2) = string(mxTd.CTdateStringEvent); + inTss.sample = xPointM3; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(3) = string(mxTd.CTdateStringEvent); + vsRef.mxHereTime = mxHereTime; + + otherwise + % original no change found, force m1, m2 rather than crash + % Elected points at 25% and 75% of waveform + vsRef.chPts = round((lastN/2),0); + xPointM1 = round((lastN * 0.25),0); + xPointM2 = round((lastN * 0.75),0); + mxHere = [xPointM1, xPointM2]; + vsRef.mxHere = mxHere; + % mxHereTime - corresponding time at these points + mxHereTime = strings(1,2); + inTss.sample = xPointM1; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(1) = string(mxTd.CTdateStringEvent); + inTss.sample = xPointM2; + mxTd = ccTimeStampSampleV2SubFunction(inTss,'findTimeSOElocal'); + mxHereTime(2) = string(mxTd.CTdateStringEvent); + vsRef.mxHereTime = mxHereTime; + end + mxPts = length(mxHere); + + % For each sensor, log the RMS value at mxHere points + % Step 2, log the data points + other = struct; % to pass extra info into p1_stateChangeColorMapV2SubFunction + other.V123yes = false; % init + other.V456yes = false; % init + + value = vo.vRMS1toEnd(mxHere,1:3); + valsIn.mxHere = mxHere; + valsIn.mxHereTime = mxHereTime; + valsIn.sensor = ["V1","V2","V3"]; + valsIn.value = round(value,0); + valsIn.value(valsIn.value < 0) = 0; % Suppress negative rms values + valsIn.valUnits = 'VoltsRMS'; + V123valsIn = valsIn; + other.V123valsIn = V123valsIn; + other.sig1 = vsRef.sig1; + [mxColorV123, mxColorIDV123] = p1_stateChangeColorMapV2SubFunction('V123',mxHere,vo,other); + other.V123yes = true; % required for V456, persist V123 + other.mxColorV123 = mxColorV123; % persist V123 + newRecs.useCol = 5; % 4 = gen1 logic, 5 = sanity logic (allows flexibility based on sensor group) + newRecs.addRows = mxPts; + newRecs.mxHere = mxHere; + newRecs.mxColor = mxColorV123; + newRecs.mxColorMapInt = mxColorIDV123; + newRecs.valsIn = V123valsIn; + newRecs.signal = vsRef.sig1(mxHere); % reminder sig1 = V123 + outLog.colValue.ChannelName = 'V123'; + [~] = p1_stateChangeDataLogV2SubFunction('addRecord',outLog,newRecs); + + + + value = vo.vRMS1toEnd(mxHere,4:6); + valsIn.mxHere = mxHere; + valsIn.mxHereTime = mxHereTime; + valsIn.sensor = ["V4","V5","V6"]; + valsIn.value = round(value,0); + valsIn.value(valsIn.value < 0) = 0; % Suppress negative rms values + valsIn.valUnits = 'VoltsRMS'; + V456valsIn = valsIn; + other.V456valsIn = V456valsIn; + other.sig2 = vsRef.sig2; + [mxColorV456, mxColorIDV456] = p1_stateChangeColorMapV2SubFunction('V456',mxHere,vo,other); + other.V456yes = true; + other.mxColorV456 = mxColorV456; + newRecs.useCol = 5; % 4 = gen1 logic, 5 = sanity logic (allows flexibility based on sensor group) + newRecs.addRows = mxPts; + newRecs.mxHere = mxHere; + newRecs.mxColor = mxColorV456; + newRecs.mxColorMapInt = mxColorIDV456; + newRecs.valsIn = V456valsIn; + newRecs.signal = vsRef.sig2(mxHere); % reminder sig2 = V456 + outLog.colValue.ChannelName = 'V456'; + [~] = p1_stateChangeDataLogV2SubFunction('addRecord',outLog,newRecs); + + + % Note: current will be plotted as % of pickup (700 amps) + % Solves the problem of normalizing when not all three phases are faulted + % Also, plot all three phases + + value = vo.iRMS1toEnd(mxHere,1:3); + valsIn.mxHere = mxHere; + valsIn.mxHereTime = mxHereTime; + valsIn.sensor = ["I1","I2","I3"]; + valsIn.value = round(value,0); + valsIn.value(valsIn.value < 0) = 0; % Suppress negative rms values + pctiSig = (vo.iRMS1toEnd(:,1:3)/refPickup) * 100; + valsIn.pctiSig = round(pctiSig,2); + valsIn.phaseMax = max(valsIn.value); % checks mx and all 3 phases + valsIn.norm600 = (600 / refPickup) * 100; % 600 amp reference line + valsIn.norm800 = (800 / refPickup) * 100; % 800 amp reference line + valsIn.valUnits = 'AmpsRMS'; + I123valsIn = valsIn; + i123Is60HZ = isIt60HzGen2SubFunction(mxHere,spc,lastN,Imatrix',vo,'I123',thr_hz60); + other.i123Is60HZ = i123Is60HZ; + other.I123valsIn = I123valsIn; + [mxColorI123, mxColorIDI123] = p1_stateChangeColorMapV2SubFunction('I123',mxHere,vo,other); + other.I123yes = true; + other.mxColorI123 = mxColorI123; + newRecs.useCol = 4; % 4 = gen1 logic, 5 = sanity logic (allows flexibility based on sensor group) + newRecs.addRows = mxPts; + newRecs.mxHere = mxHere; + newRecs.mxColor = mxColorI123; + newRecs.mxColorMapInt = mxColorIDI123; + newRecs.valsIn = I123valsIn; + signal = round(pctiSig(mxHere,:),2); + newRecs.signal = max(signal,[],2); % single data point representing 3 phases + outLog.colValue.ChannelName = 'I123'; + [~] = p1_stateChangeDataLogV2SubFunction('addRecord',outLog,newRecs); + + + % Set up figure and text box + figG6hist = figure('units','normalized','outerposition',[0 0 1 1],'Visible','off'); + + + % PLOT V123 + % vsRef works for voltage because voltage is the reference! + + p1 = axes('outerposition',[0.03 0.67 0.96 0.28]); + legP1 = plot(vsRef.attempt1sig1); % old signal + hold on; + legP2 = plot(vsRef.sig1); % signal amended with deviation + mx1Time = char(vsRef.mxHereTime(1)); + + +% X_startdate = split(wfCfg.startdate,'/'); +% new_startdate = strcat(string(X_startdate(3,1)),"-", string(X_startdate(2,1)),"-",string(X_startdate(1,1))); +% mx1Time = datetime(mx1Time,'format','HH:mm:ss.SSSSSS','TimeZone','America/New_York'); +% TimeR = char(mx1Time); +% mx1Time = mx1Time - hours(4); +% if ~isdst(datetime(new_startdate,'TimeZone','America/New_York')) +% mx1Time = mx1Time - hours(1) +% end +% mx1Time_updated = char(mx1Time); + + %mx1Time_updated = char((datetime(mx1Time, 'Format', 'yyyy-MM-dd HH:mm:ss.SSS'))); + %mx1Time_updated = char((datetime(mx1Time, 'Format', 'yyyy-MM-dd HH:mm:ss.SSS') - hours(5))); + + + X_startdate = split(wfCfg.startdate,'/'); + new_startdate = strcat(string(X_startdate(3,1)),"-", string(X_startdate(2,1)),"-",string(X_startdate(1,1))); + new_startdate = datetime(new_startdate,'format','uuuu-MM-dd HH:mm:ss.SSS','TimeZone','America/New_York') + mx1Time = datetime(mx1Time,'format','HH:mm:ss.SSS','TimeZone','America/New_York') + timeR = (new_startdate + timeofday(mx1Time)) + mx1Time = (new_startdate + timeofday(mx1Time)) - hours(4); + + if ~isdst(datetime(curDateTime,'TimeZone','America/New_York')) + mx1Time = curDateTime - hours(1) + end + + + txt = [forPNG,' Volts (V123) - 3PH - deviation (nominal PU * 3) ', ... + ' Time at m1: ',char(timeR)]; + title(txt); + ylimUp = 4.0; + ylim([-0.1 ylimUp]); + ylabel('Volts Per Unit (PH1 + PH2 + PH3)'); + xlabel('Waveform sample number'); + % RMS text set-up + stYrms = min(V123valsIn.value,[],2); + stYpu = round(vsRef.sig1(V123valsIn.mxHere),2); + legSt1 = stem(V123valsIn.mxHere,stYpu,'Marker','d','MarkerFaceColor','k','Color','k','LineStyle',':'); + txtY = zeros(length(V123valsIn.mxHere),1) + (ylimUp - 0.25); + lbls = num2str(stYrms); + text(V123valsIn.mxHere,txtY,lbls,'HorizontalAlignment','center'); + + txtY = txtY - 0.20; + text(V123valsIn.mxHere,txtY,mxColorV123(:,5),'HorizontalAlignment','center'); + + + % Samples text set-up + txtYsmp = zeros(length(V123valsIn.mxHere),1) + 0.25; + lbl2 = num2str(V123valsIn.mxHere'); + text(V123valsIn.mxHere,txtYsmp,lbl2,'HorizontalAlignment','center'); + legSt2 = stem(vsRef.chPts,vsRef.sig1(vsRef.chPts),'Marker','x','LineStyle','-.','Color','m'); + hold off; + p1.Position = plotResizeAxesTightSubFunction(p1); + + + % Plot I123 - changes detected + p2 = axes('outerposition',[0.03 0.35 0.96 0.28]); + + legP1 = plot(I123valsIn.pctiSig); % percent of pickup + hold on; + pmx = I123valsIn.phaseMax; + phaseImaxTxt = ['MAX current PH1: ',num2str(pmx(1)),' PH2: ',num2str(pmx(2)),' PH3: ',num2str(pmx(3)),' Amps']; + txt = [' --- Current (I123) normalized 3PH sum ',phaseImaxTxt]; + title(txt); + ylimUp = round(((abs(max(max(I123valsIn.pctiSig)))/100) + 1),0) * 100; + if ylimUp < 200 + ylimUp = 150; + end + ylim([-10 ylimUp]); + ylabel('Current - Percent of TCC pickup '); + xlabel('Waveform sample number'); + ln600 = [I123valsIn.norm600 I123valsIn.norm600]; + ln800 = [I123valsIn.norm800 I123valsIn.norm800]; + xEnd = length(I123valsIn.pctiSig); + legL1 = line([1 xEnd],ln600,'Color','k','LineStyle','-.'); + legL2 = line([1 xEnd],ln800,'Color','k','LineStyle','-.'); + stYrmsPH = max(I123valsIn.value,[],2); + stYpct = max(I123valsIn.pctiSig(I123valsIn.mxHere,:),[],2); + legSt1 = stem(I123valsIn.mxHere,stYpct,'Marker','d','MarkerFaceColor','k','Color','k','LineStyle','-'); + %txtY = round((stYpct*1.15),0); % add 15% offset for y position + %txtIndex = txtY < 100; + %if any(txtIndex) + % txtY = txtY + (txtIndex * 100); % mitigates crowding around small currents + %end + lbls = num2str(stYrmsPH); % current magnitude + txtY(:) = ylimUp*0.95; + text(I123valsIn.mxHere,txtY,lbls,'HorizontalAlignment','center'); + + txtY = txtY*0.95; + text(I123valsIn.mxHere,txtY,mxColorI123(:,4),'HorizontalAlignment','center'); + + hold off; + p2.Position = plotResizeAxesTightSubFunction(p2); + + + % Plot V456 --- PCRs + + p3 = axes('outerposition',[0.03 0.02 0.96 0.28]); + legP1 = plot(vsRef.attempt1sig2); % old signal + hold on; + legP2 = plot(vsRef.sig2); % signal amended with deviation + txt = 'Volts (V456) - 3PH - deviation (nominal PU * 3)'; + title(txt); + ylimUp = 4.0; + ylim([-0.1 ylimUp]); + ylabel('Volts Per Unit (PH1 + PH2 + PH3)'); + xlabel('Waveform sample number'); + + % RMS text + stYrms = min(V456valsIn.value,[],2); + stYpu = round(vsRef.sig2(V456valsIn.mxHere),2); + legSt1 = stem(V456valsIn.mxHere,stYpu,'Marker','d','MarkerFaceColor','k','Color','k','LineStyle',':'); + txtY = zeros(length(V456valsIn.mxHere),1) + (ylimUp - 0.25); + lbls = num2str(stYrms); + text(V456valsIn.mxHere,txtY,lbls,'HorizontalAlignment','center'); + + % Colors text set-up + %txtY = txtY - 0.2; + %text(V456valsIn.mxHere,txtY,mxColorV456(:,4),'HorizontalAlignment','center'); + txtY = txtY - 0.2; + text(V456valsIn.mxHere,txtY,mxColorV456(:,5),'HorizontalAlignment','center'); + + % mxHere text + txtYsmp = zeros(length(V456valsIn.mxHere),1) + 0.25; + lbl2 = num2str(V456valsIn.mxHere'); + text(V456valsIn.mxHere,txtYsmp,lbl2,'HorizontalAlignment','center'); + legSt2 = stem(vsRef.chPts,vsRef.sig2(vsRef.chPts),'Marker','x','LineStyle','-.','Color','m'); + hold off; + p3.Position = plotResizeAxesTightSubFunction(p3); + + % save plot + warning off MATLAB:print:UIControlsScaled %surpresses resizing warning + set(figG6hist,'PaperUnits','inches','PaperPosition',[0 0 17 11]); + print(figG6hist, plotPathFile,'-dpng'); + sb.plotFilePath = plotPathFile; + close(figG6hist); + + + + +end + +function sendBack = ccVectorPQmatrixVISubFunction(intoVPQMVI,wfCfg,Vmat,Imat) + sendBack = struct; + + if strcmp(intoVPQMVI.default,'getDefaults') + sendBack.default = 'set'; + sendBack.vecCount = -1; + sendBack.options = 'none'; + sendBack.flagPUoffset = false; + sendBack.iSensorInvert = 'notTested'; % check for inverted current sensors + sendBack.LOSallThreshold = 0.2; % defined LOS + return; + end + + [lastN,lastS] = size(Vmat'); + if lastN == 0 + sendBack.vecCount = 0; + return + end + + % common stuff + vecIcount = -1; + vecVcount = -1; + puOffset = -1; % if flagPUoffset is true, calculate ofset of nominal LG voltage + sendBack.vsTotal = lastS; + volts = Vmat'; + + + % correcting rms first and last cycle + rmsWin = 64; + vPlus2 = [Vmat(:,1:rmsWin),Vmat,Vmat(:,lastN-rmsWin+1:lastN)]; + vRmsPlus2 = envelope(vPlus2',rmsWin,'rms'); + voltsRMS = vRmsPlus2(rmsWin+1:lastN+rmsWin,:); + voltsRMSpu = voltsRMS / 7200; + sendBack.vRMS1toEnd = voltsRMS; + sendBack.voltsRMSpu = voltsRMSpu; + % END correction + + % calculate samples per cycle and lastN + spc = round((wfCfg.samp / wfCfg.lf),0); % samples per cycle + sendBack.spc = spc; + sendBack.lastN = wfCfg.endsamp; + + % LOSall test (vector true when all three phases < threshold) + losAll = voltsRMSpu < intoVPQMVI.LOSallThreshold; + losAllAlert = any(any(losAll),'all'); + [rx,vSensors] = size(losAll); + los123 = zeros(rx,1); + los456 = zeros(rx,1); + los123Alert = false; + los456Alert = false; + if losAllAlert && (vSensors == 3) + los123 = losAll(:,1) & losAll(:,2) & losAll(:,3); + los123Alert = any(los123); + end + if losAllAlert && (vSensors == 6) + los123 = losAll(:,1) & losAll(:,2) & losAll(:,3); + los123Alert = any(los123); + los456 = losAll(:,4) & losAll(:,5) & losAll(:,6); + los456Alert = any(los456); + end + sendBack.los123Alert = los123Alert; + sendBack.los123 = los123; + sendBack.los456Alert = los456Alert; + sendBack.los456 = los456; + sendBack.nominalLG = 7200; + sendBack.systemVoltage = '12KV'; + sendBack.losAll = losAll; + % END LOSall + + %% Single phasing test & LOSnnnV2 + sglPh123(1:rx,1) = false; + sglPh456(1:rx,1) = false; + los123V2(1:rx,1) = false; + los456V2(1:rx,1) = false; + if vSensors == 3 + los123xN = sum(losAll(:,1:3),2); + sglPh123 = ((los123xN == 1) | (los123xN == 2)); + los123V2 = (los123xN == 3); + end + if vSensors == 6 + los123xN = sum(losAll(:,1:3),2); + sglPh123 = ((los123xN == 1) | (los123xN == 2)); + los123V2 = (los123xN == 3); + los456xN = sum(losAll(:,4:6),2); + sglPh456 = ((los456xN == 1) | (los456xN == 2)); + los456V2 = (los456xN == 3); + end + sendBack.sglPh123 = sglPh123; + sendBack.sglPh456 = sglPh456; + sendBack.los123V2 = los123V2; + sendBack.los456V2 = los456V2; + + if intoVPQMVI.flagPUoffset + disp('ERROR: need to log PUoffset logic is not coded yet!!!'); + puOffset = 0; + + end + + vGood = ((0.9 <= voltsRMSpu) & (voltsRMSpu < 1.1)); + sendBack.vGood = vGood; + [~,vecVcount] = size(vGood); + sendBack.vecVcount = vecVcount; + + % convert binary vGood vector to plot data + + vThinThickGoodUp = zeros(lastN,lastS); % initialize the plot vector + vThinThickGoodDown = zeros(lastN,lastS); % initialize the plot vector + yOffSet = -2; + nextY = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastN - 65; + trueCount = sum(vGood(startHere:stopHere,:)); + for S=1:lastS + yOffSet = yOffSet + nextY; + if (trueCount(S) < (stopHere - startHere)) % at least one false or all false (thin line if all false) + vThinThickGoodUp(:,S) = yOffSet + (vGood(:,S) * oneOn); + vThinThickGoodDown(:,S) = yOffSet - (vGood(:,S) * oneOn); + end + if (trueCount(S) >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + vThinThickGoodUp(:,S) = yOffSet + (vGood(:,S) * (oneAll + 0.07)); % attempt to emphasize true + vThinThickGoodDown(:,S) = yOffSet + (vGood(:,S) * oneAll); + end + end + thinThickVgood = [vThinThickGoodUp, vThinThickGoodDown]; + sendBack.thinThickVgood = thinThickVgood; + + % end convert binary vGood vector to plot data + + % vPQ // IEEE vSag OR vSwell // make thinThickfor PQ only + vSag = (0.1 <= voltsRMSpu) & (voltsRMSpu < 0.9); + sendBack.vSag = vSag; + + vSwell = 1.1 <= voltsRMSpu; + sendBack.vSwell = vSwell; + + vPQ = vSag | vSwell; + sendBack.vPQ = vPQ; + + % convert binary vPQ vector to plot data + vThinThickPQUp = zeros(lastN,lastS); % initialize the plot vector + vThinThickPQDown = zeros(lastN,lastS); % initialize the plot vector + yOffSet = -2; + nextY = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastN - 65; + trueCount = sum(vPQ(startHere:stopHere,:)); + for S=1:lastS + yOffSet = yOffSet + nextY; + if (trueCount(S) < (stopHere - startHere)) % at least one false or all false (thin line if all false) + vThinThickPQUp(:,S) = yOffSet + (vPQ(:,S) * oneOn); + vThinThickPQDown(:,S) = yOffSet - (vPQ(:,S) * oneOn); + end + if (trueCount(S) >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + vThinThickPQUp(:,S) = yOffSet + (vPQ(:,S) * (oneAll + 0.07)); % attempt to emphasize true + vThinThickPQDown(:,S) = yOffSet + (vPQ(:,S) * oneAll); + end + end + thinThickPQ = [vThinThickPQUp, vThinThickPQDown]; + sendBack.thinThickPQ = thinThickPQ; + + + vLOS = voltsRMSpu < 0.1; + sendBack.vLOS = vLOS; + % convert binary vLOS vector to plot data + % + vThinThickLOSUp = zeros(lastN,lastS); % initialize the plot vector + vThinThickLOSDown = zeros(lastN,lastS); % initialize the plot vector + yOffSet = -2; + nextY = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastN - 65; + trueCount = sum(vLOS(startHere:stopHere,:)); + for S=1:lastS + yOffSet = yOffSet + nextY; + if (trueCount(S) < (stopHere - startHere)) % at least one false or all false (thin line if all false) + vThinThickLOSUp(:,S) = yOffSet + (vLOS(:,S) * oneOn); + vThinThickLOSDown(:,S) = yOffSet - (vLOS(:,S) * oneOn); + end + if (trueCount(S) >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + vThinThickLOSUp(:,S) = yOffSet + (vLOS(:,S) * (oneAll + 0.07)); % attempt to emphasize true + vThinThickLOSDown(:,S) = yOffSet + (vLOS(:,S) * oneAll); + end + end + thinThickLOS = [vThinThickLOSUp, vThinThickLOSDown]; + sendBack.thinThickLOS = thinThickLOS; + + + [lastNi,lastSi] = size(Imat'); + + rmsWin = 64; + iPlus2 = [Imat(:,1:rmsWin),Imat,Imat(:,lastNi-rmsWin+1:lastNi)]; + iRmsPlus2 = envelope(iPlus2',rmsWin,'rms'); + currentRMS = iRmsPlus2(rmsWin+1:lastNi+rmsWin,:); + sendBack.iRMS1toEnd = currentRMS; + % end correction + + iGood = ((8 <= currentRMS) & (currentRMS < 800)); + sendBack.iGood = iGood; + + % convert binary iGood vector to plot data + % + iThinThickGoodUp = zeros(lastNi,lastSi); % initialize the plot vector + iThinThickGoodDown = zeros(lastNi,lastSi); % initialize the plot vector + yOffSet = -2; + nextY = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(iGood(startHere:stopHere,:)); + for S=1:lastSi + yOffSet = yOffSet + nextY; + if (trueCount(S) < (stopHere - startHere)) % at least one false or all false (thin line if all false) + iThinThickGoodUp(:,S) = yOffSet + (iGood(:,S) * oneOn); + iThinThickGoodDown(:,S) = yOffSet - (iGood(:,S) * oneOn); + end + if (trueCount(S) >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + iThinThickGoodUp(:,S) = yOffSet + (iGood(:,S) * (oneAll + 0.07)); % attempt to emphasize true + iThinThickGoodDown(:,S) = yOffSet + (iGood(:,S) * oneAll); + end + end + thinThickIgood = [iThinThickGoodUp, iThinThickGoodDown]; + sendBack.thinThickIgood = thinThickIgood; + + + % fault current + iFault = (800 <= currentRMS); + sendBack.iFault = iFault; + sendBack.ibsF = iFault(1,:); + sendBack.caeF = iFault(end,:); + + iThinThickUp = zeros(lastNi,lastSi); % initialize the plot vector + iThinThickDown = zeros(lastNi,lastSi); % initialize the plot vector + yOffSet = -2; + nextY = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(iFault(startHere:stopHere,:)); + for S=1:lastSi + yOffSet = yOffSet + nextY; + if (trueCount(S) < (stopHere - startHere)) % at least one false or all false (thin line if all false) + iThinThickUp(:,S) = yOffSet + (iFault(:,S) * oneOn); + iThinThickDown(:,S) = yOffSet - (iFault(:,S) * oneOn); + end + if (trueCount(S) >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + iThinThickUp(:,S) = yOffSet + (iFault(:,S) * (oneAll + 0.07)); % attempt to emphasize true + iThinThickDown(:,S) = yOffSet + (iFault(:,S) * oneAll); + end + end + thinThickIfault = [iThinThickUp, iThinThickDown]; + sendBack.thinThickIfault = thinThickIfault; + + % end iFault + + % no current + iNot = (currentRMS < 8); + sendBack.iNot = iNot; + % convert binary vLOS vector to plot data + % + iThinThickUp = zeros(lastNi,lastSi); % initialize the plot vector + iThinThickDown = zeros(lastNi,lastSi); % initialize the plot vector + yOffSet = -2; + nextY = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(iNot(startHere:stopHere,:)); + for S=1:lastSi + yOffSet = yOffSet + nextY; + if (trueCount(S) < (stopHere - startHere)) % at least one false or all false (thin line if all false) + iThinThickUp(:,S) = yOffSet + (iNot(:,S) * oneOn); + iThinThickDown(:,S) = yOffSet - (iNot(:,S) * oneOn); + end + if (trueCount(S) >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + iThinThickUp(:,S) = yOffSet + (iNot(:,S) * (oneAll + 0.07)); % attempt to emphasize true + iThinThickDown(:,S) = yOffSet + (iNot(:,S) * oneAll); + end + end + thinThickNot = [iThinThickUp, iThinThickDown]; + sendBack.thinThickNot = thinThickNot; + + [~,sensors] = size(vGood); + vGood3PH = sum(vGood,2) == sensors; % all sensors must be good + sendBack.vGood3PH = vGood3PH; + [firstX3,lastX3] = size(vGood3PH); + thinThickUp = zeros(firstX3,lastX3); % initialize the plot vector + thinThickDown = zeros(firstX3,lastX3); % initialize the plot vector + yOffSet = 4; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(vGood3PH(startHere:stopHere,:)); + if (trueCount < (stopHere - startHere)) % at least one false or all false (thin line if all false) + thinThickUp = yOffSet + (vGood3PH * oneOn); + thinThickDown = yOffSet - (vGood3PH * oneOn); + end + if (trueCount >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + thinThickUp = yOffSet + (vGood3PH * (oneAll + 0.07)); % attempt to emphasize true + thinThickDown = yOffSet + (vGood3PH * oneAll); + end + thinThickVolt3PH = [thinThickUp, thinThickDown]; + vPQ3PH = sum(vPQ,2) > 0; % any single PQ event detected + sendBack.vPQ3PH = vPQ3PH; + [firstX3,lastX3] = size(vPQ3PH); + thinThickUp = zeros(firstX3,lastX3); % initialize the plot vector + thinThickDown = zeros(firstX3,lastX3); % initialize the plot vector + yOffSet = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(vPQ3PH(startHere:stopHere,:)); + if (trueCount < (stopHere - startHere)) % at least one false or all false (thin line if all false) + thinThickUp = yOffSet + (vPQ3PH * oneOn); + thinThickDown = yOffSet - (vPQ3PH * oneOn); + end + if (trueCount >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + thinThickUp = yOffSet + (vPQ3PH * (oneAll + 0.07)); % attempt to emphasize true + thinThickDown = yOffSet + (vPQ3PH * oneAll); + end + thinThickVolt3PH = [thinThickVolt3PH, thinThickUp, thinThickDown]; + + vLOS3PH = sum(vLOS,2) > 0; % any single LOS event detected + sendBack.vLOS3PH = vLOS3PH; + [firstX3,lastX3] = size(vLOS3PH); + thinThickUp = zeros(firstX3,lastX3); % initialize the plot vector + thinThickDown = zeros(firstX3,lastX3); % initialize the plot vector + yOffSet = 0; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(vLOS3PH(startHere:stopHere,:)); + if (trueCount < (stopHere - startHere)) % at least one false or all false (thin line if all false) + thinThickUp = yOffSet + (vLOS3PH * oneOn); + thinThickDown = yOffSet - (vLOS3PH * oneOn); + end + if (trueCount >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + thinThickUp = yOffSet + (vLOS3PH * (oneAll + 0.07)); % attempt to emphasize true + thinThickDown = yOffSet + (vLOS3PH * oneAll); + end + thinThickVolt3PH = [thinThickVolt3PH, thinThickUp, thinThickDown]; + sendBack.thinThickVolt3PH = thinThickVolt3PH; + + [~,sensors] = size(iGood); + iGood3PH = sum(iGood,2) == sensors; % all sensors must be good + sendBack.iGood3PH = iGood3PH; + [firstX3,lastX3] = size(iGood3PH); + thinThickUp = zeros(firstX3,lastX3); % initialize the plot vector + thinThickDown = zeros(firstX3,lastX3); % initialize the plot vector + yOffSet = 4; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(iGood3PH(startHere:stopHere,:)); + if (trueCount < (stopHere - startHere)) % at least one false or all false (thin line if all false) + thinThickUp = yOffSet + (iGood3PH * oneOn); + thinThickDown = yOffSet - (iGood3PH * oneOn); + end + if (trueCount >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + thinThickUp = yOffSet + (iGood3PH * (oneAll + 0.07)); % attempt to emphasize true + thinThickDown = yOffSet + (iGood3PH * oneAll); + end + thinThickCurrent3PH = [thinThickUp, thinThickDown]; + + iFault3PH = sum(iFault,2) > 0; % any single Fault event detected + sendBack.iFault3PH = iFault3PH; + [firstX3,lastX3] = size(iFault3PH); + thinThickUp = zeros(firstX3,lastX3); % initialize the plot vector + thinThickDown = zeros(firstX3,lastX3); % initialize the plot vector + yOffSet = 2; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(iFault3PH(startHere:stopHere,:)); + if (trueCount < (stopHere - startHere)) % at least one false or all false (thin line if all false) + thinThickUp = yOffSet + (iFault3PH * oneOn); + thinThickDown = yOffSet - (iFault3PH * oneOn); + end + if (trueCount >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + thinThickUp = yOffSet + (iFault3PH * (oneAll + 0.07)); % attempt to emphasize true + thinThickDown = yOffSet + (iFault3PH * oneAll); + end + thinThickCurrent3PH = [thinThickCurrent3PH, thinThickUp, thinThickDown]; + + % end FAULT 3 phase + % begin iNot (no current) 3 phase + iNot3PH = sum(iNot,2) > 0; % any single LOS event detected + sendBack.iNot3PH = iNot3PH; + [firstX3,lastX3] = size(iNot3PH); + thinThickUp = zeros(firstX3,lastX3); % initialize the plot vector + thinThickDown = zeros(firstX3,lastX3); % initialize the plot vector + yOffSet = 0; + oneOn = 0.27; + oneAll = 0.7; + startHere = 65; + stopHere = lastNi - 65; + trueCount = sum(iNot3PH(startHere:stopHere,:)); + if (trueCount < (stopHere - startHere)) % at least one false or all false (thin line if all false) + thinThickUp = yOffSet + (iNot3PH * oneOn); + thinThickDown = yOffSet - (iNot3PH * oneOn); + end + if (trueCount >= (stopHere - startHere)) % always true (in display), minimize true offset (raised double true line) + thinThickUp = yOffSet + (iNot3PH * (oneAll + 0.07)); % attempt to emphasize true + thinThickDown = yOffSet + (iNot3PH * oneAll); + end + thinThickCurrent3PH = [thinThickCurrent3PH, thinThickUp, thinThickDown]; + sendBack.thinThickCurrent3PH = thinThickCurrent3PH; + +sendBack.vecCount = vecIcount + vecVcount; +sendBack.vecIcount = vecIcount; + + +end + +function sendBack = ccClassifyV2SubFunction(gbbIn,gbbID,functionName,setTo,setOther,action) +sendBack = struct; +% TODO add action 'method2' allowing 1 to N updates + +gid = [gbbIn.GBBid]; +g = strcmp(gid,gbbID); +dataRow = gid(g); +if isempty(dataRow) + sendBack = gbbIn; % modify nothing + % TODO error log that gbbID not found + return; +end + +if sum(g) > 1 + sendBack = gbbIn; % modify nothing + % TODO error more than one record found (unexpected case) + return; +end + +if (~isempty(dataRow) && strcmp(action,'updateOne') && (sum(g) == 1)) + newGbb = gbbIn; + classifyThis = gbbIn(g); + if ((classifyThis.TestCount > 0) && ~strcmp(classifyThis.TestResult,setTo)) % conflicting test results + classifyThis.TestConflict = string(['conflict-',functionName,'-',setTo]); + end + if classifyThis.TestCount == 0 + classifyThis.ResultDeterminedByFunction = string(functionName); + classifyThis.TestResult = string(setTo); + classifyThis.Other = string(setOther); + end + classifyThis.TestCount = classifyThis.TestCount + 1; + newGbb(g) = classifyThis; + sendBack = newGbb; + return; +end +sendBack = gbbIn; +end + +function sendBack = plotResizeAxesTightSubFunction(axesName) + outerpos = axesName.OuterPosition; + ti = axesName.TightInset; + left = outerpos(1) + ti(1); + bottom = outerpos(2) + ti(2); + test_width = outerpos(3) - ti(1) - ti(3); + test_height = outerpos(4) - ti(2) - ti(4); + sendBack = [left bottom test_width test_height]; +end + +function sFlag = setSensorFlagSubFunction(sensorConfig,sensorName) + sFlag = false; + flagNames = split(sensorConfig,'-'); + foundIt = find(contains(flagNames,sensorName)); + if foundIt + sFlag = true; + end +end + +function sendBack = ccTimeStampSampleV2SubFunction(ccTSSinTO,action) + format longG; % eliminate pesky scientific nonotation most of the time + sendBack = struct; + + + + % New Option SOE date time format in local time + if strcmp(action,'defaultSOElocal') + replayDateFormat = 'yyyy-mm-dd HH:MM:SS.FFF'; % move to ccStructDefaults + sendBack.dateFormatIn = replayDateFormat; % basic change from original + sendBack.dateFormatToLog = replayDateFormat; + + %sendBack.comtradeDT = ccTSSinTO; % test date + %sendBack.dateIn = ccTSSinTO; %test date + + %needs formatted from 10/08/2022 15:56:53.885636 + + %sendBack.comtradeDT = '2022/10/08 15:56:53.885'; + AllDateTime = split(ccTSSinTO) + Date = AllDateTime(1,1) + Time = char(AllDateTime(2,1)) + Time = Time(1:end-3) + + AllDate = split(Date,'/') + DD = char(AllDate(1,1)) + MM = char(AllDate(2,1)) + YYYY = char(AllDate(3,1)) + myDateTime = strcat(YYYY,'-',MM,'-',DD) + myDateTime = [myDateTime,' ',Time] + + + sendBack.dateIn = myDateTime + + sendBack.sample = 333; + sendBack.lineFreq = 60; + sendBack.samplesPerCycle = 64; + return; + end + + + sendBack.goodData = true; %fatal errors need to set this to false + sendBack.error1 = 'none'; %see error checking for assignment + sendBack.error2 = 'none'; %see error checking for assignment + sendBack.error3 = 'none'; %see error checking for assignment + +%% +% TODO: this needs to be passed in so that all date formats can be changed +% in a common place + %comtradeDTformat = 'dd/mm/yyyy,HH:MM:SS.FFF'; % move to ccStructDefaults + %replayDateFormat = 'yyyy-mm-dd HH:MM:SS.FFF'; % move to ccStructDefaults +% end TODO + dateFormatIn = ccTSSinTO.dateFormatIn; + dateFormatToLog = ccTSSinTO.dateFormatToLog; + + sampleFreq = ccTSSinTO.lineFreq * ccTSSinTO.samplesPerCycle; + deltaSec = ccTSSinTO.sample / sampleFreq; + maxMsecSampleError = 0.001 * sampleFreq; % samples represented by 1 msec + + %% swap between soe and comtrade + if strcmp(action,'findTimeSOElocal') + ccTSSinTO.comtradeDT = ccTSSinTO.dateIn; + end + %% begin date manipulation - COMTRADE date + + CTdateNum0 = datenum(ccTSSinTO.comtradeDT,dateFormatIn); + + sampleTime0 = CTdateNum0 + seconds(0); %convert to duration + CTdateString0 = datestr(CTdateNum0,dateFormatToLog); %convert to replay date time + % Calculate cycleTime using COMTRADE date time stamp + h = sampleTime0; + h.Format = 'h'; + cycH = str2double(datestr(h,'HH')); + secSince00 = cycH * 3600; %convert hours to seconds since midnight + m = sampleTime0; + m.Format = 'm'; + cycM = str2double(datestr(m,'MM')); + secSince00 = secSince00 + (cycM * 60); %add minutes converted to seconds + s = sampleTime0; + s.Format = 's'; + cycS = str2double(datestr(s,'SS.FFF')); + secSince00 = secSince00 + cycS; + cycleTime0 = secSince00 * ccTSSinTO.lineFreq; %cycles since midnight + + + %% calculate the date time detals at the sample number + sampleTimeEvent = CTdateNum0 + seconds(deltaSec); + CTdateStringEvent = datestr(sampleTimeEvent,dateFormatToLog); + + % Calculate cycleTime using specified sample data point + h = sampleTimeEvent; + h.Format = 'h'; + cycH = str2double(datestr(h,'HH')); + secSince00 = cycH * 3600; %convert hours to seconds since midnight + m = sampleTimeEvent; + m.Format = 'm'; + cycM = str2double(datestr(m,'MM')); + secSince00 = secSince00 + (cycM * 60); %add minutes converted to seconds + s = sampleTimeEvent; + s.Format = 's'; + cycS = str2double(datestr(s,'SS.FFF')); + secSince00 = secSince00 + cycS; + cycleTimeEvent = secSince00 * ccTSSinTO.lineFreq; %cycles since midnight + %sendBack.cycleTimeEvent = cycleTimeEvent; + + %% Error check - has the date rolled over + % method 1: cycleTimeAtSample < cycleTimeStart + % method 2: cycleTimeAtSample > max number of cycles in a day + if (cycleTimeEvent < cycleTime0) + errorNote = ['Sample cycle time: ',num2str(cycleTimeEvent) ... + ' is less than start cycle: ',num2str(cycleTime0)]; + sendBack.error1 = errorNote; + sendBack.goodData = false; + end + maxNumCycles = (24 * 3600) * ccTSSinTO.lineFreq; + if (cycleTimeEvent >= maxNumCycles) + errorNote = ['Date roll over detected - Sample cycle time: ',num2str(cycleTimeEvent) ... + ' is greater than max cycles in a day: ',num2str(maxNumCycles)]; + sendBack.error2 = errorNote; + sendBack.goodData = false; + end + + %% return the new date time (at the sample passed in) + sendBack.CTdateNum0 = CTdateNum0; + CTdateNumEvent = datenum(CTdateStringEvent); + sendBack.CTdateNumEvent = CTdateNumEvent; + sendBack.CTdateString0 = CTdateString0; + sendBack.CTdateStringEvent = CTdateStringEvent; + sampleXDT = split(CTdateStringEvent,' '); + sendBack.sampleDate = char(sampleXDT(1)); %TODO error check array size + sendBack.sampleTime = char(sampleXDT(2)); %TODO error check array size + sendBack.sampleTime0 = sampleTime0; + sendBack.sampleTimeEvent = sampleTimeEvent; + sendBack.deltaSec = deltaSec; + sendBack.cycleTime0 = cycleTime0; + sendBack.cycleTimeEvent = cycleTimeEvent; + cycleDelta = cycleTimeEvent - cycleTime0; + sendBack.cycleDelta = cycleDelta; + + + %% Calculation confirmation check + % Use the delta time (in seconds (or cycles) to confirm the sample + % number that was passed in + % Open issue, time resolution limit: + % Milisecond resoulution insufficient if sampling frequency is + % greater than 999 samples per SECOND + % Determine alloable error - resolution 1 milisec = x samples + % If x > 1, then time resolution insufficient to accurately check + sampleCheck = cycleDelta * ccTSSinTO.samplesPerCycle; + sampleError = ccTSSinTO.sample - sampleCheck; % Error in samples caused by milisec resolution + sendBack.sampleError = sampleError; + + if (abs(sampleError) > maxMsecSampleError) + errorNote = ['Sample error greater than expected: ',num2str(sampleError) ... + ' 1 mSec resolution max sample error: ',num2str(maxMsecSampleError)]; + sendBack.error3 = errorNote; + sendBack.goodData = false; + end + +end + +function PH60 = isIt60HzGen2SubFunction(mxHere,spc,lastN,iDat,vo,sensorGroup,thr_hz60) + howMany = length(mxHere); + PH60(howMany,4) = false; % PH1, PH2, PH3, col4/true = all phases are 60HZ + spchalf = round((spc/2),0); % for +/- 1/2 cycle calc + if strcmp(sensorGroup,'I123') + iCols = 1:3; + end + if strcmp(sensorGroup,'I456') + iCols = 4:6; + end + for hm = 1:howMany + mxStart = mxHere(hm) - spchalf; + mxEnd = mxHere(hm) + spchalf - 1; + % trap for start / end of file limits + if mxStart < 1 + mxStart = 1; + mxEnd = mxStart + spc - 1; + end + if mxEnd > lastN + mxStart = lastN - spc + 1; + mxEnd = lastN; + end + % check if cycleX is 60 Hz + cycleX = iDat(mxStart:mxEnd,iCols); + normalizeIt = max(vo.iRMS1toEnd(mxStart:mxEnd,iCols)) * sqrt(2); + if max(normalizeIt) < 1 + normalizeIt = [1, 1, 1]; % trap for small current + end + cycleXn = cycleX ./ normalizeIt; + + % From Matlab fft example + L = spc; % Length of signal + w1 = cycleXn; % TODO - see if each phase needs to be checked! + Y = fft(w1); + P2 = abs(Y/L); + P1 = P2((1:L/2+1),:); + P1((2:end-1),:) = 2*P1((2:end-1),:); + at60 = P1(2,:); % 60HZ data point is the second + % Figure out if any single phase has 60 HZ + + PH60(hm,1:3) = (at60 > thr_hz60); + PH60(hm,4) = all(PH60(hm,1:3)); + end + + + +end + +function [mxColor, mxColorID] = p1_stateChangeColorMapV2SubFunction(sensorGroup,mxHere,vo,other) + mxColor = struct; + mxColorID = struct; + global currentFolder + % minimum current flow + minCurrentFlow = 1; % 1 amp RMS + lastN = vo.lastN; + spc = vo.spc; + mxPts = length(mxHere); + colorID = zeros(mxPts,4); % PH1, PH2, PH3, signal (3 phase equivalent) + + path2 = strcat(currentFolder,'\colorIndex.txt') + gpaCI = importGPAcolorIntNestedFunction(path2); % gpaCI = GPA color integer + + +% losCheck = false; +% singlePhase = false; + % initialize color, all cases + clearColor = 'dkGrayTBD'; + colorName = clearColorName(mxPts,clearColor); + colorID = assignColorIDs(colorName,gpaCI); + % voltage 3 phase sanity check + sanityColor = strings(mxPts,1); + sanityColor(:,1) = clearColor; +% sanityColor2 = strings(mxPts,1); +% sanityColor2(:,1) = clearColor; + + % Assign colors - voltage cases + if (strcmp(sensorGroup,'V123') || strcmp(sensorGroup,'V456')) + iRnge = 1:3; % normal case, but MOS exception + [~, cx] = size(vo.iFault(1,:)); + if ((cx == 6) && strcmp(sensorGroup,'V456')) + iRnge = 4:6; % when processing V456 and I4:6 exists + end + if strcmp(sensorGroup,'V123') + mxRange = 1:3; + signal = other.sig1; + end + if strcmp(sensorGroup,'V456') + mxRange = 4:6; + signal = other.sig2; + end + sigVals = signal(mxHere); + + % Good source + thisColor = 'redSource'; +% thisIndex = vo.vGood(mxHere,mxRange); +% thisIndex = [thisIndex, vo.vGood3PH(mxHere)]; + thisIndex = (vo.vRMS1toEnd(mxHere,mxRange)/vo.nominalLG) > 0.9; + ti4 = thisIndex(:,1) & thisIndex(:,2) & thisIndex(:,3); + thisIndex = [thisIndex, ti4]; + colorName(thisIndex) = thisColor; + % sanity check - good source + sanityIndex = sigVals > 2.75; + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info good source: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + % PQ - no fault + thisColor = 'tanPQ'; + thisIndex = vo.vPQ(mxHere,mxRange); + thisIndex = [thisIndex, vo.vPQ3PH(mxHere)]; + colorName(thisIndex) = thisColor; + % sanity check - PQ no fault + sanityIndex = ((sigVals <= 2.75) & (sigVals > 0.4)); + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info PQ no fault: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + % PQ with fault present + thisColor = 'pinkFltPQ'; + thisIndex = (vo.vPQ(mxHere,mxRange) & vo.iFault(mxHere,iRnge)); + thisIndex2 = vo.vPQ3PH(mxHere) & vo.iFault3PH(mxHere); + thisIndex = [thisIndex, thisIndex2]; + colorName(thisIndex) = thisColor; + % sanity check - PQ with fault + sanityIndex = ((sigVals <= 2.75) & (sigVals > 0.4) & vo.iFault3PH(mxHere)); + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info PQ fault present: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + % LOS test + thisColor = 'blackLOS'; + thisIndex = vo.losAll(mxHere,mxRange); + if strcmp(sensorGroup,'V123') + thisIndex = [thisIndex, vo.los123V2(mxHere)]; + end + if strcmp(sensorGroup,'V456') + thisIndex = [thisIndex, vo.los456V2(mxHere)]; + end + colorName(thisIndex) = thisColor; + % sanity check - LOS test + sanityIndex = (sigVals <= 0.4); + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info LOS: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + % Single phase over-ride (only applies to total) + thisColor = 'orgSglPH'; + if strcmp(sensorGroup,'V123') + thisIndex(:,4) = vo.sglPh123(mxHere); + end + if strcmp(sensorGroup,'V456') + thisIndex(:,4) = vo.sglPh456(mxHere); + end + colorName(thisIndex) = thisColor; + + % sanity check - singe phase test + sanityIndex = (sigVals > 0.4) & (sigVals <= 1.8); + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info single phase test: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + % Add sanity check colors as column 5 + colorName = [colorName, sanityColor]; + colorID = assignColorIDs(colorName,gpaCI); + mxColor = colorName; + mxColorID = colorID; + return; + end % END Voltage + + % Assign i colors - PCR current cases + % TODO SEL current cases!!! + if (strcmp(sensorGroup,'I123') && other.V123yes && other.V456yes) + mxRange = 1:3; + % Initialize to greenOpen to see if this improves logic flow + % Experiment to see how many false opens are created + thisColor = 'greenOpen'; + tmp = ones(mxPts,4); + thisIndex = tmp > 0; + colorName(thisIndex) = thisColor; + + % Good current (looking at the max phase) + thisColor = 'redCurrent'; +% thisIndex = vo.iGood(mxHere,mxRange); +% thisIndex = [thisIndex, vo.iGood3PH(mxHere)]; + thisRMS = vo.iRMS1toEnd(mxHere,:); + thisRMS(thisRMS < 0) = 0; % suppress negative RMS current + thisIndex = thisRMS > 1; % weak if i has DC offset + maxRMS = round(max(thisRMS,[],2),0); + thisIndex(:,4) = maxRMS > 3; % weak if i has DC offset + % amend index if current small and is 60HZ + smallI = (maxRMS <=3) & other.i123Is60HZ(:,4); + thisIndex(:,4) = thisIndex(:,4) | smallI; % 60HZ override small currents + colorName(thisIndex) = thisColor; + % VI+V analysis --- necessary for sanity checks + sig1x3 = other.sig1(mxHere); + sig2x3 = other.sig2(mxHere); + viplusv123 = (sig1x3 .* maxRMS) + sig1x3; + viplusv456 = (sig2x3 .* maxRMS) + sig2x3; + % sanity check - current is flowing + sanityIndex = (viplusv123 > 6) & (viplusv456 > 6); + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info has current flow: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + % Test for pickup between 600 and 800 amps (highZ , high load) + thisColor = 'ltBluePickUp'; + pickupYes = (vo.iRMS1toEnd(mxHere,mxRange) > 600) & ... + (vo.iRMS1toEnd(mxHere,mxRange) <= 800); + thisIndex = [pickupYes, any(pickupYes,2)]; + colorName(thisIndex) = thisColor; + + % Test for fault for png + thisColor = 'blueFault800'; + faultYes = (vo.iRMS1toEnd(mxHere,mxRange) > 800); + thisIndex = [faultYes, any(faultYes,2)]; + colorName(thisIndex) = thisColor; + + % Test for open (no current and not LOS both sides) + % Careful, messes with your mind + thisColor = 'greenOpen'; + notLOS = (~vo.vLOS(mxHere,1:3) & ~vo.vLOS(mxHere,4:6)); + openCheck123 = vo.iNot(mxHere,mxRange) & notLOS; + thisIndex = [openCheck123, all(openCheck123,2)]; + colorName(thisIndex) = thisColor; + % sanity check - current is not flowing + s1yes = other.sig1(mxHere) > 0.4; + s2no = other.sig2(mxHere) <= 0.4; + s2yes = other.sig2(mxHere) > 0.4; + s1no = other.sig1(mxHere) <= 0.4; + sanityIndex = ((s1yes & s2no) | (s1no & s2yes)) & smallI; % one good source, one bad source and low I not 60HZ + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info Open detected: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + + + % Test for no source both directions, force current blackLOS + % May tend to mask mis-opeartion, only care if misOp + % Is later assigned a different color + thisColor = 'blackLOS'; + noSrc = vo.vLOS(mxHere,1:3) & vo.vLOS(mxHere,4:6); + thisIndex = [noSrc, all(noSrc,2)]; + colorName(thisIndex) = thisColor; + % sanity check - total LOS +% sanityIndex = ((other.sig1(mxHere) <= 0.4) & (other.sig2(mxHere) <= 0.4)); + sanityIndex = s1no & s2no; + sanityColor(sanityIndex) = thisColor; + sanityCheck = strcmp(colorName(:,4),sanityColor(:)); + if all(sanityCheck) + disp('Debug info Open LOS: colorName4 matches sanityColor'); + %else + %callOutDifferences(mxHere,sanityCheck,colorName(:,4),sanityColor(:,1),sigVals) + end + + % COLUMN #4 analysis -- leave individual phases untouched + % Test for protection trip toward V456 + % Requires an open after a fault + % mxPts >= 2 (can't compare a single data point) + if mxPts >= 2 && (any(strcmp(colorName(:,4),'blueFault800')) || any(strcmp(colorName(:,4),'ltBluePickUp'))) + V123src = ~(vo.vLOS(mxHere,1) & vo.vLOS(mxHere,2) & vo.vLOS(mxHere,3)); + V456los = vo.vLOS(mxHere,4) & vo.vLOS(mxHere,5) & vo.vLOS(mxHere,6); + didTrip = testForProtectionTrip456(mxPts,colorName(:,4),V123src,V456los); + colorName(:,4) = didTrip; + end + + % COLUMN #4 analysis -- leave individual phases untouched + % Test for protection trip toward V123 + % Requires an open after a fault + if mxPts >= 2 && (any(strcmp(colorName(:,4),'blueFault800')) || any(strcmp(colorName(:,4),'ltBluePickUp'))) + V123los = vo.vLOS(mxHere,1) & vo.vLOS(mxHere,2) & vo.vLOS(mxHere,3); + V456src = ~(vo.vLOS(mxHere,4) & vo.vLOS(mxHere,5) & vo.vLOS(mxHere,6)); + didTrip = testForProtectionTrip123(mxPts,colorName(:,4),V123los,V456src); + colorName(:,4) = didTrip; + end + + % COLUMN #4 analysis -- leave individual phases untouched + % Test for mis-operation + % Fault precedes no source both sides + if mxPts >= 2 && (any(strcmp(colorName(:,4),'blueFault800')) || any(strcmp(colorName(:,4),'ltBluePickUp'))) + V123los = vo.vLOS(mxHere,1) & vo.vLOS(mxHere,2) & vo.vLOS(mxHere,3); + V456los = vo.vLOS(mxHere,4) & vo.vLOS(mxHere,5) & vo.vLOS(mxHere,6); + misOp = testForMisOperation(mxPts,colorName(:,4),V123los,V456los); + colorName(:,4) = misOp; + end + % Add sanity color and return + colorName = [colorName,sanityColor]; + colorID = assignColorIDs(colorName,gpaCI); + mxColor = colorName; + mxColorID = colorID; + return; + end % end PCR current + + % Assign i colors - SEL I123 current cases + % TODO SEL/MOS I456 current cases!!! +% var = 'i have not entered loop' +% if (strcmp(sensorGroup,'I123') && other.V123yes && ~other.V456yes) +% var = 'i have entered loop' +% mxRange = 1:3; +% +% % sanity, confirm CB has source (used for a couple cases) +% sanityIndexHasSource = ((min(vo.vRMS1toEnd(mxHere,mxRange),[],2))/vo.nominalLG) > 0.1; % worst phase not zero +% % Open check - CTs are accurate, +% % so a 1 amp threshold should be a good test +% thisColor = 'greenOpen'; +% thisRMS = vo.iRMS1toEnd(mxHere,:); +% thisRMS(thisRMS < 0) = 0; % suppress negative RMS current +% thisRMS = round(thisRMS,0); +% thisIndex = thisRMS < 1; % weak if i has DC offset +% thisIndex(:,4) = any(thisIndex,2); +% colorName(thisIndex) = thisColor; +% % Sanity check, has source and no current +% sanityIndex = thisIndex(:,4) & sanityIndexHasSource; +% sanityColor(sanityIndex) = thisColor; +% +% +% % Good current (looking at the max phase) +% thisColor = 'redCurrent'; +% thisIndex = thisRMS > 1; % weak if i has DC offset +% %maxRMS = round(max(thisRMS,[],2),0); +% thisIndex(:,4) = maxRMS > 1; % weak if i has DC offset +% colorName(thisIndex) = thisColor; +% +% sanityIndex = sanityIndexHasSource & thisIndex(:,4); % has voltage and current +% sanityColor(sanityIndex) = thisColor; +% +% % Test for pickup between 600 and 800 amps (highZ , high load) +% thisColor = 'ltBluePickUp'; +% pickupYes = (vo.iRMS1toEnd(mxHere,mxRange) > 600) & ... +% (vo.iRMS1toEnd(mxHere,mxRange) <= 800); +% thisIndex = [pickupYes, any(pickupYes,2)]; +% colorName(thisIndex) = thisColor; +% +% % Test for fault +% thisColor = 'blueFault800'; +% faultYes = (vo.iRMS1toEnd(mxHere,mxRange) > 800); +% thisIndex = [faultYes, any(faultYes,2)]; +% colorName(thisIndex) = thisColor; +% +% % Test for LOS +% thisColor = 'blackLOS'; +% thisIndex = (vo.vRMS1toEnd(mxHere,mxRange)/vo.nominalLG) <= 0.1; % no source +% thisIndex = [thisIndex, all(thisIndex,2)]; +% colorName(thisIndex) = thisColor; +% % sanity check - total LOS +% sanityIndex = ~sanityIndexHasSource; +% sanityColor(sanityIndex) = thisColor; +% +% % COLUMN #4 analysis -- leave individual phases untouched +% % Test for protection trip toward Load +% % Requires an open after a fault +% % mxPts >= 2 (can't compare a single data point) +% if mxPts >= 2 && (any(strcmp(colorName(:,4),'blueFault800')) || any(strcmp(colorName(:,4),'ltBluePickUp'))) +% didTrip = CBtestForProtectionTrip(mxPts,colorName(:,4),sanityIndexHasSource); +% colorName(:,4) = didTrip; +% end +% +% % Add sanity color and return +% colorName = [colorName,sanityColor]; +% colorID = assignColorIDs(colorName,gpaCI); +% mxColor = colorName; +% mxColorID = colorID; +% return; +% end + +function configreplayGPAcolorIndex = importGPAcolorIntNestedFunction(filename, dataLines) +if nargin < 2 + dataLines = [2, Inf]; +end + +%% Setup the Import Options and import the data +opts = delimitedTextImportOptions("NumVariables", 5); + +% Specify range and delimiter +opts.DataLines = dataLines; +opts.Delimiter = "\t"; + +% Specify column names and types +opts.VariableNames = ["GPAint", "Color", "Red", "Green", "Blue"]; +opts.VariableTypes = ["double", "string", "double", "double", "double"]; + +% Specify file level properties +opts.ExtraColumnsRule = "ignore"; +opts.EmptyLineRule = "read"; + +% Specify variable properties +opts = setvaropts(opts, "Color", "WhitespaceRule", "preserve"); +opts = setvaropts(opts, "Color", "EmptyFieldRule", "auto"); + +% Import the data +configreplayGPAcolorIndex = readtable(filename, opts); + +end + +end + + + +function colorName = clearColorName(mxPts,clearColor) + colorName = strings(mxPts,4); % PH1, PH2, PH3, signal (3 phase equivalent) + colorName(:,:) = clearColor; + % call to find ID +end + +function colorID = assignColorIDs(cNames,gpaCI) + [r, c] = size(cNames); + colorID = zeros(r,c); + for rix = 1:r + for cix = 1:c + gpaRowI1 = strcmp(gpaCI.Color,cNames(rix,cix)); + colorID(rix,cix) = gpaCI.GPAint(gpaRowI1); + end + end +end + + +function didTrip = testForProtectionTrip456(mxPts,colorName4,V123src,V456los) + didTrip = colorName4; % return unmodified if did not trip + for m = 1:mxPts-1 + if strcmp(colorName4(m),'blueFault800') || strcmp(colorName4(m),'ltBluePickUp') + if V123src(m+1) && V456los(m+1) + didTrip(m+1) = 'greenTrip'; + end + end + end +end + + +function didTrip = testForProtectionTrip123(mxPts,colorName4,V123los,V456src) + didTrip = colorName4; % return unmodified if did not trip + for m = 1:mxPts-1 + if strcmp(colorName4(m),'blueFault800') || strcmp(colorName4(m),'ltBluePickUp') + if V123los(m+1) && V456src(m+1) + didTrip(m+1) = 'greenTrip'; + end + end + end +end + +function misOp = testForMisOperation(mxPts,colorName4,V123los,V456los) + misOp = colorName4; % return unmodified if did not trip + for m = 1:mxPts-1 + if strcmp(colorName4(m),'blueFault800') || strcmp(colorName4(m),'ltBluePickUp') + if V123los(m+1) && V456los(m+1) + misOp(m+1) = 'blackLOS'; + end + end + end +end + +function didTrip = CBtestForProtectionTrip(mxPts,colorName4,sanityIndexHasSource) + didTrip = colorName4; + for m = 1:mxPts-1 + if strcmp(colorName4(m),'blueFault800') || strcmp(colorName4(m),'ltBluePickUp') + if strcmp(colorName4(m+1),'greenOpen') && sanityIndexHasSource(m+1) + didTrip(m+1) = 'greenTrip'; + end + end + end +end +function configreplayGPAcolorIndex = importGPAcolorIntSubFunction(filename, dataLines) +if nargin < 2 + dataLines = [2, Inf]; +end + +% Setup the Import Options and import the data +opts = delimitedTextImportOptions("NumVariables", 5); + +% Specify range and delimiter +opts.DataLines = dataLines; +opts.Delimiter = "\t"; + +% Specify column names and types +opts.VariableNames = ["GPAint", "Color", "Red", "Green", "Blue"]; +opts.VariableTypes = ["double", "string", "double", "double", "double"]; + +% Specify file level properties +opts.ExtraColumnsRule = "ignore"; +opts.EmptyLineRule = "read"; + +% Specify variable properties +opts = setvaropts(opts, "Color", "WhitespaceRule", "preserve"); +opts = setvaropts(opts, "Color", "EmptyFieldRule", "auto"); + +% Import the data +configreplayGPAcolorIndex = readtable(filename, opts); + +end + +function sb = p1_stateChangeDataLogV2SubFunction(action,inLog,newRecords,Circuit,Phase,Orientation,wfCfg) + global currentFolder + sb = struct; + + + if strcmp(action,'getDefaults') + sb.default = 'set'; + sb.actionList = {'getDefaults','getDataTypes','newFile','setCommonValues','addRecord','addRecToDatabase','writeTaskListToDB'}; + sb.addToDB = false; % if true, attempts to add records to database + % column names for data record to be logged + % divided into groups to allow 1 to N data values per sensor channel + taskInfo = {'EventID', ... % keys and sorting + 'SOE_ID', ... % GPA SOE_groupID? + 'Circuit', ... + 'DeviceName', ... + 'ChannelName', ... + 'SOEdateTimeLocal', ... + 'systemVoltage'}; % Expected power flow direction + + + mv1toN = { 'mxNum', ... % measurement number (typically 1 to 3) + 'mxHereSamp', ... + 'mxTimeLocal', ... + 'mxValue', ... + 'mxColor', ... % Human color name + 'mxColorMapInt'}; + + linkInfo = {'PlotFileName','IncidentID'}; + colNames = [taskInfo, mv1toN, linkInfo]; + sb.colNames = colNames; + sb.colValue = cell2struct(colNames,colNames,2); % data record + sb.mv1toN = cell2struct(mv1toN,mv1toN,2); % measured values data set + return; + end % END initialization + + + if strcmp(action,'getDataTypes') + + intList = {'EventID','SOE_ID','mxNum','mxHereSamp','mxColorMapInt', ... + 'IncidentID'}; + + floatList = {'systemVoltage','mxValue'}; + + dateList = {'SOEdateTimeLocal','mxTimeLocal'}; + + textList = {'Circuit','DeviceName','ChannelName','mxColor'}; + bigTextList = {'PlotFileName'}; + pkList = {'EventID','DeviceName','ChannelName','mxHereSamp'}; + sb.intList = intList; + sb.floatList = floatList; + sb.dateList = dateList; + sb.textList = textList; + sb.bigTextList = bigTextList; + sb.pkList = pkList; + sb.lastColumn = lastColumn; + return; + end % END getDataTypes + + %% Create file and write column names + if strcmp(action,'newFile') + path3 = strcat(currentFolder,'\Output\SOE_Log.txt') + fOutId = fopen(path3,'a+'); % open file + [~,maxCol] = size(inLog.colNames); + for colX = 1:maxCol-1 + fprintf(fOutId,'%s\t',string(inLog.colNames(colX))); + end + fprintf(fOutId,'%s\n',string(inLog.colNames(maxCol))); %terminate row with new line + fclose(fOutId); + return; % nothing sent back, no data in "inLog" yet + end % END first row + + %% Set common values + % + if strcmp(action,'setCommonValues') + sb = inLog; % must preserve what was passed in + cv = inLog.colValue; % local copy to reduce struct name size + cv.EventID = wfCfg.eventID; + cv.SOE_ID = wfCfg.soeID; + cv.Circuit = Circuit; + cv.DeviceName = wfCfg.recording_device; + cv.SOEdateTimeLocal = wfCfg.soeTime; + voltagelevel = extract(cv.Circuit,4); + voltagelevel = char(voltagelevel); + if voltagelevel == '2' + cv.systemVoltage = '12 kV'; + elseif voltagelevel == '4' + cv.systemVoltage = '46 kV'; + else + cv.systemVoltage = '4 kV'; + end + cv.IncidentID = wfCfg.incidentID; + sb.colValue = cv; % send back assigned values + return; + end + + + + + %% Append file with values measured by sensors + % log all other process data as name - value pairs + % need to loop and write all GBB results + if strcmp(action,'addRecord') + sb = inLog; % must preserve what was passed in + addRows = newRecords.addRows; + useCol = newRecords.useCol; + valsIn = newRecords.valsIn; + if addRows < 1 % nothing to log + return; + end + % build a structure of data points + newRec = struct([]); + for i = 1:addRows + thisRow = inLog.colValue; + %thisRow.SOEdateTimeLocal = thisTask.DateTimeSOE; + %thisRow.systemVoltage = thisTask.VoltClassLL; + thisRow.mxNum = i; + thisRow.mxHereSamp = newRecords.mxHere(i); + thisRow.mxTimeLocal = char(datetime(valsIn.mxHereTime(i),'Format','yyyy-MM-dd HH:mm:ss.SSS')); + %thisRow.mxTimeLocal = char(datetime(valsIn.mxHereTime(i),'Format','yyyy-MM-dd HH:mm:ss.SSS') - hours(5)); + thisRow.mxValue = newRecords.signal(i); + thisRow.mxColor = newRecords.mxColor(i,useCol); + thisRow.mxColorMapInt = newRecords.mxColorMapInt(i,useCol); + if i == 1 + newRec = thisRow; % forces newRec to have same structure as thisRow + end + newRec(i) = thisRow; + end + path4 = strcat(currentFolder,'\Output\SOE_Log.txt') + writetable(struct2table(newRec),path4,'Delimiter','\t','WriteMode','Append'); % note: fields must be scalar + return; + + return; + end + +end + +function sb = p1_voltSensorReferenceSubFunction(wfCfg,Vmatrix,Imatrix) + sb = struct; % sb abbreviation for sendBack + sb.changes = 0; % case 3 sensors and no changes + sb.chPts = -1; + + % Vector analysis, waveforms and rms calculations + intoVPQMVI.default = 'getDefaults'; + intoVPQMVI = ccVectorPQmatrixVISubFunction(intoVPQMVI,wfCfg,Vmatrix,Imatrix); + vo = ccVectorPQmatrixVISubFunction(intoVPQMVI,wfCfg,Vmatrix,Imatrix); + + signalPerPhase = vo.vRMS1toEnd; + signalPU = signalPerPhase / vo.nominalLG; + attempt1sig1 = sum(signalPU(:,1:3),2); % superceded by deviation + sb.attempt1sig1 = attempt1sig1; + % logic change, 3PH equivalent, less relative deviation + V123rmsAdd = round((sum(vo.vRMS1toEnd(:,1:3),2)/vo.nominalLG),2); + relDev = abs(vo.vRMS1toEnd(:,1:3) - vo.nominalLG)/vo.nominalLG; + V123relDev = round(sum(relDev,2),2); + sig1 = V123rmsAdd - V123relDev; + sig1(sig1<0) = 0; % Avoid negative calculations + changeHere1 = findchangepts(sig1,'Statistic','mean','MaxNumChanges',2); + sig1DidChange = true; + sb.sig1 = sig1; + sb.sig2 = -1; % mitigate crash if only 3 sensors + if isempty(changeHere1) + sig1DidChange = false; + sb.changes = 0; % case 3 sensors and no changes + sb.chPts = -1; + % NOTE: calling function must trap and ingnore + elseif length(changeHere1) == 2 + changeHere1 = samePoint(changeHere1); + sb.changes = length(changeHere1); % case 3 sensors + sb.chPts = changeHere1; + end + + if vo.vsTotal == 6 + attempt1sig2 = sum(signalPU(:,4:6),2); % superceded by deviation + sb.attempt1sig2 = attempt1sig2; + % logic change, 3PH equivalent, less relative deviation + V456rmsAdd = round((sum(vo.vRMS1toEnd(:,4:6),2)/vo.nominalLG),2); + relDev = abs(vo.vRMS1toEnd(:,4:6) - vo.nominalLG)/vo.nominalLG; + V456relDev = round(sum(relDev,2),2); + sig2 = V456rmsAdd - V456relDev; + sig2(sig2<0) = 0; % Avoid negative calculations + sb.sig2 = sig2; + VxVyOpenDetect = abs(sig2 - sig1); + isItOpen = (VxVyOpenDetect > (5/100)); + % Simple check for trip (or open with two different sources) + if sum(isItOpen) > 90 + itIsOpen = true; + else + itIsOpen = false; % or open with two different sources + end + sb.itIsOpen = itIsOpen; + changeHere2 = findchangepts(sig2,'Statistic','mean','MaxNumChanges',2); % change points + sig2DidChange = true; + if isempty(changeHere2) + sig2DidChange = false; + elseif length(changeHere2) == 2 + changeHere2 = samePoint(changeHere2); + end + + % Determine the number of changes, and which ones to use + if sig1DidChange && sig2DidChange + % confirm one or both are useful signals + usefulSig1 = usefulSignal(sig1); + usefulSig2 = usefulSignal(sig2); + % abort if neither is useful + if ~usefulSig1 && ~usefulSig2 + sb.changes = 0; + sb.chPts = -1; + return; + end + % Use sig1 because sig2 is not useful + if usefulSig1 && ~usefulSig2 + sb.changes = length(changeHere1); + sb.chPts = changeHere1; + return; + end + % Use sig2 because sig1 is not useful + if ~usefulSig1 && usefulSig2 + sb.changes = length(changeHere2); + sb.chPts = changeHere2; + return; + end + % Both signals are useful, several cases need to be examined + % Case 1: single change each, is it the same point? + if ((length(changeHere1) == 1) && (length(changeHere2) == 1)) + % merge change if approx same point + changeHere = [changeHere1; changeHere2]; + changeHere = samePoint(changeHere); + sb.changes = length(changeHere); + sb.chPts = changeHere; + return; + end + % Case 2: V123 has 2 changes, V456 has 1 change, ignore V456 + % TODO, find exmaple case and determine if min and max is better + if ((length(changeHere1) == 2) && (length(changeHere2) == 1)) + commonFlag = confirmCommonPoint(changeHere1,changeHere2); + if ~commonFlag + logMe = "Case 2: Two signals missing a common change point"; + disp(logMe); + end + % Use V123 changes + sb.changes = length(changeHere1); + sb.chPts = changeHere1; + return; + end + % Case 3: V456 has 2 changes, V123 has 1 change, ignore V123 + % TODO, find exmaple case and determine if min and max is better + if ((length(changeHere1) == 1) && (length(changeHere2) == 2)) + commonFlag = confirmCommonPoint(changeHere1,changeHere2); + if ~commonFlag + logMe = "Case 3: Two signals missing a common change point"; + disp(logMe); + end + % Use V123 changes + sb.changes = length(changeHere2); + sb.chPts = changeHere2; + return; + end + % Case 4: both have 2 changes, are they similar points? + % See test data for case 4 in comments at end of file + if ((length(changeHere1) == 2) && (length(changeHere2) == 2)) + commonFlag = confirmCommonPoint(changeHere1,changeHere2); + if ~commonFlag + logMe = "Case 4: Two signals missing a common change point"; + disp(logMe); + end + % check if approx same point + changeHereX = [changeHere1(1); changeHere2(1)]; + changeHereX = samePoint(changeHereX); + changeHereY = [changeHere1(2); changeHere2(2)]; + changeHereY = samePoint(changeHereY); + changeHere = [changeHereX; changeHereY]; + changeHere = samePoint(changeHere); + % Assume points between min and max are transients + if length(changeHere) > 2 + changeHere = [min(changeHereX);max(changeHereY)]; + end + sb.changes = length(changeHere); + sb.chPts = changeHere; + return; + end + end + end + +end + +function sb = samePoint(changeHere) + sb = changeHere; % assume different points + + howClose = abs(diff(changeHere)); + if howClose <= 90 + sb = round((sum(changeHere)/2),0); + end +end + +function sb = usefulSignal(sigPU) + sb = false; + minChange = 0.15; % in PU + minSignal = 0.5; % in PU + + someValue = (sigPU > minSignal); + howMany = sum(someValue); + + maxLessMin = abs(max(sigPU)) - abs(min(sigPU)); + + if (howMany > 90) && (maxLessMin > minChange) + sb = true; + end +end + +function sb = confirmCommonPoint(changeSet1,changeSet2) + sb = false; + sameFirst = false; + sameLast = false; + commonPoint = false; + + firstCheck = samePoint([changeSet1(1);changeSet2(1)]); + if length(firstCheck) == 1 + sameFirst = true; + end + lastCheck = samePoint([changeSet1(end);changeSet2(end)]); + if length(lastCheck) == 1 + sameLast = true; + end + if (length(changeSet1) == 2) && (length(changeSet2) == 2) + firstLast = samePoint([changeSet1(1);changeSet2(2)]); + if length(firstLast) == 1 + commonPoint = true; + end + lastFirst = samePoint([changeSet1(2);changeSet2(1)]); + if length(lastFirst) == 1 + commonPoint = true; + end + end + sb = any([sameFirst, sameLast, commonPoint]); +end + +function classificationGBB1 = importGBBlistFile150SubFunction(filename, startRow, endRow) + +delimiter = '\t'; +if nargin<=2 + startRow = 2; + endRow = inf; +end + +formatSpec = '%s%s%s%s%s%s%s%s%f%s%s%s%s%s%[^\n\r]'; + + +fileID = fopen(filename,'r'); + +dataArray = textscan(fileID, formatSpec, endRow(1)-startRow(1)+1, 'Delimiter', delimiter, 'TextType', 'string', 'HeaderLines', startRow(1)-1, 'ReturnOnError', false, 'EndOfLine', '\r\n'); +for block=2:length(startRow) + frewind(fileID); + dataArrayBlock = textscan(fileID, formatSpec, endRow(block)-startRow(block)+1, 'Delimiter', delimiter, 'TextType', 'string', 'HeaderLines', startRow(block)-1, 'ReturnOnError', false, 'EndOfLine', '\r\n'); + for col=1:length(dataArray) + dataArray{col} = [dataArray{col};dataArrayBlock{col}]; + end +end + +fclose(fileID); + +classificationGBB1 = table(dataArray{1:end-1}, 'VariableNames', {'GBBid','Active','Group','Bucket','Bin','OperatingDevice','Outcome','Revision','TestCount','TestResult','ResultDeterminedByFunction','TestConflict','TBD','Other'}); + +end + +function Vmatrix = OrientationCheck(Vmatrix, Orientation) + if strcmp('YX',Orientation) + Vmatrix_X = Vmatrix(1:3,:); + Vmatrix_Y = Vmatrix(4:6,:); + Vmatrix = vertcat(Vmatrix_Y,Vmatrix_X); + end +return +end \ No newline at end of file diff --git a/Intellirupters/toGPA_G7_Replay/MakeReplay.m b/Intellirupters/toGPA_G7_Replay/MakeReplay.m new file mode 100644 index 0000000..f2982da --- /dev/null +++ b/Intellirupters/toGPA_G7_Replay/MakeReplay.m @@ -0,0 +1,206 @@ +%Austin Replay +%Purpose of this script is to generate a replay text file to pass to +%Stephen at GPA so he can integrate into SOE Engine + +function MakeReplay(Setting) + text_file = Setting.SOELogPath; + TSx = 1; + NLT_Array = []; + fid = fopen(text_file, 'rt'); + datacell = textscan(fid, '%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s', 'delimiter', '\t', 'HeaderLines', 1); + fclose(fid); + cycle = 1/60; + %compiling columns from tsv file generated by AustinG7 + SOE_ID = datacell{2}; + Event_ID = datacell{1}; + Circuit = datacell{3}; + DeviceName = datacell{4}; + ChannelName = datacell{5}; + SOEdateTimeLocal = datacell{6}; + mxTimeLocal = datacell{10}; + mxColorMapInt = datacell{13}; + + SensorName = strcat(Circuit,'-',DeviceName,'.',ChannelName); + + TempArray = [SensorName,mxTimeLocal,mxColorMapInt,SOE_ID,Event_ID]; + MasterArray = []; + for jj = 1:length(TempArray(:,1)) + if str2double(TempArray{jj,4}) == Setting.SOE_ID + MasterArray = vertcat(MasterArray, TempArray(jj,:)); + end + end + if length(MasterArray) == 0 + return + end + MasterArray = sortrows(MasterArray,2); + + StartTime = datetime(MasterArray(1,2),'Format','yyyy-MM-dd HH:mm:ss.SSS') - seconds(0.010); + EndTime = datetime(MasterArray(end,2),'Format','yyyy-MM-dd HH:mm:ss.SSS') + seconds(0.010); + TimeLength = between(StartTime,EndTime); + TimeLength = time(TimeLength); + NewTimeArray = unique(vertcat(StartTime, MasterArray(:,2), EndTime)); + + %need to find number of devices present + uniqueSensors = unique(SensorName); + unq = size(unique(SensorName)); + NoOfDevices = unq(1); + + %time slots and duration of SOE event + format = "hh:mm:ss.SSSS"; + secs = string(TimeLength,format); + secs = second(datetime(secs)); + milliseconds = 1000*secs; + TimeSlots = round(milliseconds / TSx); + + + %make an array containing all the time slots (one for each millisecond) + base = 0; + oldSensor = ''; + for jj = 1:length(uniqueSensors(:,1)) + NewTime = StartTime; + + %creating sensor order numbers required for replay + SensorOrder = split(uniqueSensors(jj,1),'.'); + SensorOrderNew = SensorOrder(1,1); + if ~strcmp(oldSensor,SensorOrderNew) + base = base + 100; + end + oldSensor = SensorOrderNew; + SensorOrder2 = SensorOrder(2,1); + if strcmp(SensorOrder2,'V123') + digit = base + 1; + elseif strcmp(SensorOrder2,'I123') + digit = base + 2; + else + digit = base + 3; + end + + + + for ii = 1:length(NewTimeArray) + %NewTime = NewTime + seconds(0.001); + timeForArray = string(NewTimeArray(ii,1)); + sensorForArray = string(uniqueSensors(jj)); + t11 = datevec(datenum(NewTimeArray(1,1))); + t22 = datevec(datenum(NewTimeArray(ii,1))); + elapsedMS = (etime(t22,t11)*1000); + elapsedSECS = floor(elapsedMS / 1000); + elapsedCYCLES = floor(elapsedMS / (cycle*1000)); + + if ii - 1 == 0 + t33 = t11; + else + t33 = datevec(datenum(NewTimeArray(ii-1,1))); + end + t44 = datevec(datenum(NewTimeArray(ii,1))); + timeGAP_MS = (etime(t44,t33)*1000); + + NLT_Array_NewRow = [sensorForArray digit ii timeForArray 'dummy' elapsedMS elapsedSECS elapsedCYCLES timeGAP_MS]; + NLT_Array = vertcat(NLT_Array, NLT_Array_NewRow); + end + end + + %moving colors over to new array from existing array + for xx = 1:length(NLT_Array(:,1)) + for yy = 1:length(MasterArray(:,1)) + if strcmp(NLT_Array(xx,1), MasterArray(yy,1)) && strcmp(NLT_Array(xx,4), MasterArray(yy,2)) + NLT_Array(xx,5) = MasterArray(yy,3); + end + end + end + + %filling in new array's missing color gaps + for zz = 1:length(uniqueSensors(:,1)) + mxColor_ID = 0; + for aa = 1:length(NLT_Array(:,1)) + if strcmp(uniqueSensors(zz,1), NLT_Array(aa,1)) + test = (ismissing(NLT_Array(aa,5)) | strcmp(NLT_Array(aa,5),'dummy')); + if test + NLT_Array(aa,5) = mxColor_ID; + else + mxColor_ID = NLT_Array(aa,5); + end + end + end + end + + %% Here we will add the additional columns needed for the replay + %adding SensorTypeID + array_length = size(NLT_Array,1); + for jj = 1:array_length + tf = contains(NLT_Array(jj,1),'I123'); + if tf + SensorTypeID(jj,1) = 2; + else + SensorTypeID(jj,1) = 1; + end + end + NLT_Array = horzcat(SensorTypeID, NLT_Array); + + %% Here we will add an additional column for NLTDataTypeID which is always 1 + %adding NLTDataTypeID + for jj = 1:array_length + NLTDataTypeID(jj,1) = 1; + end + NLT_Array = horzcat(NLTDataTypeID, NLT_Array); + + %% Here we will add EventID as an additional column + for jj = 1:array_length + NLTEventID_column(jj,1) = "-1"; + for ii = 1:length(MasterArray(:,1)) + if strcmp(NLT_Array(jj,3), MasterArray(ii,1)) && strcmp(NLT_Array(jj,6), MasterArray(ii,2)) + NLTEventID_column(jj,1) = MasterArray(ii,5); + end + end + end + NLT_Array = horzcat(NLTEventID_column, NLT_Array); + + %% Here we will add the TSxUnits which will be only in milliseconds to avoid losses + for jj = 1:array_length + TSxUnits(jj,1) = "mSec"; + end + NLT_Array = horzcat(TSxUnits, NLT_Array); + + %% Here we will add the TSx which will always be 1 milliseconds + for jj = 1:array_length + TSx(jj,1) = "1"; + end + NLT_Array = horzcat(TSx, NLT_Array); + + %% Here we will add the SOE ID + for jj = 1:array_length + SOEID_column(jj,1) = Setting.SOE_ID; + end + NLT_Array = horzcat(SOEID_column, NLT_Array); + + %% Now we rearrange the Sensor Names to match what device names + for i = 1:length(uniqueSensors) + if length(split(uniqueSensors(i,1),'-')) > 2 + rearrange = split(uniqueSensors(i,1),'-'); + rearrange2 = split(rearrange(3,1),'.'); + NewSensorName = rearrange(1,1) + "-" + rearrange2(1,1) + "-" + rearrange(2,1) + '.' + rearrange2(2,1); + for j = 1:height(NLT_Array) + NLT_Array(j,7); + uniqueSensors(i,1); + if strcmp(NLT_Array(j,7), uniqueSensors(i,1)) + NLT_Array(j,7) = NewSensorName; + + end + end + end + end + + %% Here we add the map display - currents show by default + for i = 1:height(NLT_Array) + if contains(NLT_Array(i,7), 'I123') + Display(i,1) = '1'; + else + Display(i,1) = '0'; + end + end + NLT_Array = horzcat(NLT_Array, Display); + + pathway = Setting.ReplayPath; + writematrix(NLT_Array,pathway,'Delimiter','\t'); +end + diff --git a/Intellirupters/toGPA_G7_Replay/MakeReplay.prj b/Intellirupters/toGPA_G7_Replay/MakeReplay.prj new file mode 100644 index 0000000..0dc7074 --- /dev/null +++ b/Intellirupters/toGPA_G7_Replay/MakeReplay.prj @@ -0,0 +1,139 @@ + + + MakeReplay + + + 1.0 + + + + + + + + \MakeReplay\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\MakeReplay\for_testing + ${PROJECT_ROOT}\MakeReplay\for_redistribution_files_only + ${PROJECT_ROOT}\MakeReplay\for_redistribution + ${PROJECT_ROOT}\MakeReplay + false + + subtarget.net.component + + MakeReplay + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + MakeReplay + Analytic + + C:\Projects\epb-matlab\Intellirupters\toGPA_G7_Replay + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\MakeReplay.m + + + + + ${PROJECT_ROOT}\MakeReplay.m + + + + + + + + + + C:\Projects\epb-matlab\Intellirupters\toGPA_G7_Replay\MakeReplay\for_testing\MakeReplay.dll + C:\Projects\epb-matlab\Intellirupters\toGPA_G7_Replay\MakeReplay\for_testing\MakeReplay_overview.html + C:\Projects\epb-matlab\Intellirupters\toGPA_G7_Replay\MakeReplay\for_testing\MakeReplayNative.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/Intellirupters/toGPA_G7_Replay/SnC_G7_Replay.prj b/Intellirupters/toGPA_G7_Replay/SnC_G7_Replay.prj new file mode 100644 index 0000000..ca102a2 --- /dev/null +++ b/Intellirupters/toGPA_G7_Replay/SnC_G7_Replay.prj @@ -0,0 +1,139 @@ + + + SnC_G7_Replay + + + 1.0 + + + + + + + + \SnC_G7_Replay\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\SnC_G7_Replay\for_testing + ${PROJECT_ROOT}\SnC_G7_Replay\for_redistribution_files_only + ${PROJECT_ROOT}\SnC_G7_Replay\for_redistribution + ${PROJECT_ROOT}\SnC_G7_Replay + false + + subtarget.net.component + + SnC_G7_Replay + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + SnC_G7_Replay + Analytic + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G7_Replay + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\AustinG7.m + + + + + ${PROJECT_ROOT}\AustinG7.m + + + + + + + + + + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G7_Replay\SnC_G7_Replay\for_testing\SnC_G7_Replay.dll + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G7_Replay\SnC_G7_Replay\for_testing\SnC_G7_Replay_overview.html + C:\Projects\epb-matlab\Intellirupters\toGPA_SnC_G7_Replay\SnC_G7_Replay\for_testing\SnC_G7_ReplayNative.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/toGPA_G7_Replay/classification.txt b/Intellirupters/toGPA_G7_Replay/classification.txt similarity index 100% rename from toGPA_G7_Replay/classification.txt rename to Intellirupters/toGPA_G7_Replay/classification.txt diff --git a/toGPA_G7_Replay/colorIndex.txt b/Intellirupters/toGPA_G7_Replay/colorIndex.txt similarity index 100% rename from toGPA_G7_Replay/colorIndex.txt rename to Intellirupters/toGPA_G7_Replay/colorIndex.txt diff --git a/Intellirupters/toGPA_G7_Replay/groupVoltCurr.m b/Intellirupters/toGPA_G7_Replay/groupVoltCurr.m new file mode 100644 index 0000000..b326880 --- /dev/null +++ b/Intellirupters/toGPA_G7_Replay/groupVoltCurr.m @@ -0,0 +1,70 @@ +%% groupVoltCurr.m - This function takes in a structure containing the +% analog channels from a COMTRADE file. +% Inputs: +% o analogChannels: Structure containing the analog channels +% +% Outputs: +% o Imatrix: Matrix of current vectors, ordered in 1, 2, 3 or A, B, C +% fashion +% o Vmatrix: Matrix of voltage vectors, ordered in 1, 2, 3 or A, B, C +% fashion +% o numSensors: The total number of sensors collected (not included +% Di/Dt channels) +% o sensorInfo: Information about the sensors. This argument tells if +% the sensors use A,B,C, or 1,2,3 orientation. +% *sensorInfo.type = 'ABC', or '123'. +% +% Written by: Aaron Wilson, 6/22/2018 + +function [Imatrix,Vmatrix,numSensors,sensorInfo] = groupVoltCurr(analogChannels) + + N = numel(fieldnames(analogChannels)); + + % Temporary matrices to store stuff in: + Itemp = []; Vtemp = []; + Inames = []; Vnames = []; + + % Names of sensors in analog channel struct + sensorNames = fieldnames(analogChannels); + + for k = 1:numel(fieldnames(analogChannels)) + + channelName = sensorNames{k}; + + % Ignoring Di/Dt channels + if strcmp(channelName(1),'D') + continue + % Ignoring VDC channels + elseif length(channelName)>2 && strcmp(channelName(1:3),'VDC') + continue + elseif length(channelName)>3 && strcmp(channelName(1:4),'VBAT') + continue + elseif strcmp(channelName(1:2),'VS') + continue + + elseif strcmp(channelName(1),'I') + nextCurUp = getfield(analogChannels,channelName); + Itemp = cat(1,Itemp, nextCurUp'); + Inames = cat(1,Inames,channelName); + + elseif strcmp(channelName(1),'V') + nextVolUp = getfield(analogChannels,channelName); + Vtemp = cat(1,Vtemp,nextVolUp'); + Vnames = cat(1,Vnames,channelName); + + end + + end + + if (strcmp(Inames(1,2),'1') || strcmp(Inames(1,2),'2') || strcmp(Inames(1,2),'3')) + sensorInfo.type = '123'; + elseif (strcmp(Inames(1,2),'A') || strcmp(Inames(1,2),'B') || strcmp(Inames(1,2),'C')) + sensorInfo.type = 'ABC'; + end + + Imatrix = Itemp; + Vmatrix = Vtemp; + numSensors = size(Inames,1) + size(Vnames,1); + +end + diff --git a/toGPA_G7_Replay/readCFG_COMTRADE.m b/Intellirupters/toGPA_G7_Replay/readCFG_COMTRADE.m similarity index 100% rename from toGPA_G7_Replay/readCFG_COMTRADE.m rename to Intellirupters/toGPA_G7_Replay/readCFG_COMTRADE.m diff --git a/toGPA_G7_Replay/readDAT_COMTRADE.m b/Intellirupters/toGPA_G7_Replay/readDAT_COMTRADE.m similarity index 100% rename from toGPA_G7_Replay/readDAT_COMTRADE.m rename to Intellirupters/toGPA_G7_Replay/readDAT_COMTRADE.m diff --git a/toGPA_G7_Replay/AustinG7.m b/SEL/toGPA_G7_Replay/AustinG7.m similarity index 95% rename from toGPA_G7_Replay/AustinG7.m rename to SEL/toGPA_G7_Replay/AustinG7.m index c06c22d..d0fe521 100644 --- a/toGPA_G7_Replay/AustinG7.m +++ b/SEL/toGPA_G7_Replay/AustinG7.m @@ -1,53 +1,51 @@ - -clc -clear all -global currentFolder -currentFolder = pwd; -folderPath = horzcat(currentFolder,'\Input'); -D = genpath(folderPath); -fileFolders = split(D,';'); -max = size(fileFolders); -max = max(1,1); -i = 0; -for i = 2:max - fileFolders{i,1}; - currentfile = string(fileFolders{i,1}); - S = strcat(currentfile,'\','*.DAT'); - - files = dir(S); - for file = files' - the_size = file.bytes; - if the_size > 10000 - path1 = strcat(currentFolder,'\','classification.txt'); - GBB_local = importGBBlistFile150SubFunction(path1); - dat_file = strcat(currentfile,'\',file.name); - dat_file = char(dat_file); - cfg_file = strcat(dat_file(1:end-3),'CFG'); - waveFormCfg = readCFG_COMTRADE(cfg_file); - waveFormDat = readDAT_COMTRADE(dat_file,waveFormCfg); - [Imat,Vmat,~,~] = groupVoltCurr(waveFormDat.analog); - p1_g6stateChangeHistoryV2(waveFormCfg,Vmat,Imat,dat_file,i,currentFolder); - i = i + 1; - end - +function tags = p1_g6stateChangeHistoryV2Analytic(Voltage, Current, Fs, Setting) + tags = []; + if ~Setting.ExecuteAnalytic + return end + Vmat = []; + Imat = []; + Vmat = cat(1, Vmat, Voltage(:,7)'); % VA + Vmat = cat(1, Vmat, Voltage(:,8)'); % VB + Vmat = cat(1, Vmat, Voltage(:,9)'); % VC + Imat = cat(1, Imat, Current(:,5)'); % IA + Imat = cat(1, Imat, Current(:,6)'); % IB + Imat = cat(1, Imat, Current(:,7)'); % IC + + classificationsPath = convertStringsToChars(Setting.ClassificationsPath); + GBB_local = importGBBlistFile150SubFunction(classificationsPath); + GBB_local = table2struct(GBB_local); + + cfg = struct; + cfg.station_name = convertStringsToChars(Setting.Station); + cfg.recording_device = convertStringsToChars(Setting.Device); + cfg.lf = Setting.SystemFrequency; + cfg.samp = Fs; + cfg.endsamp = Setting.SampleCount; + cfg.startdate = convertStringsToChars(Setting.EventDate); + cfg.starttime = convertStringsToChars(Setting.EventTime); + cfg.eventID = Setting.Event_ID; + cfg.soeID = Setting.SOE_ID; + cfg.soeTime = Setting.SOE_Time; + cfg.incidentID = Setting.Incident_ID; + + dat_file = convertStringsToChars("\\\\\" + Setting.InputFilename); + outputFolder = convertStringsToChars(Setting.OutputFolder); - + global currentFolder + currentFolder = outputFolder + result = p1_g6stateChangeHistoryV2(cfg, Vmat, Imat, dat_file, 0, outputFolder); + + if isfield(result, 'plotFilePath') + tag = struct; + tag.Name = 'G7 State Change Plot'; + tag.Data = struct; + tag.Data.PlotFilePath = result.plotFilePath; + tags = [tags, tag]; + end end - - -% GBB_local = importGBBlistFile150SubFunction('D:\_gbbR06.11\classificationGBB2.xx.txt'); -% dat_file = 'D:\GBB_CT\PCR_inBox\CT-145290\HAL201-HB4408\HAL201-HB4408_WFCAP10.1670370786000.DAT'; -% cfg_file = strcat(dat_file(1:end-3),'CFG'); -% waveFormCfg = readCFG_COMTRADE(cfg_file); -% waveFormDat = readDAT_COMTRADE(dat_file,waveFormCfg); -% [Imat,Vmat,~,~] = groupVoltCurr(waveFormDat.analog); -% p1_g6stateChangeHistoryV2(waveFormCfg,Vmat,Imat,dat_file); - - - function sb = p1_g6stateChangeHistoryV2(wfCfg,Vmatrix,Imatrix,dat_file,i,currentFolder) @@ -460,6 +458,7 @@ function sb = p1_g6stateChangeHistoryV2(wfCfg,Vmatrix,Imatrix,dat_file,i,current warning off MATLAB:print:UIControlsScaled %surpresses resizing warning set(figG6hist,'PaperUnits','inches','PaperPosition',[0 0 17 11]); print(figG6hist, plotPathFile,'-dpng'); + sb.plotFilePath = plotPathFile; close(figG6hist); @@ -1527,10 +1526,11 @@ function sb = p1_stateChangeDataLogV2SubFunction(action,inLog,newRecords,Circuit if strcmp(action,'setCommonValues') sb = inLog; % must preserve what was passed in cv = inLog.colValue; % local copy to reduce struct name size - cv.SOE_ID = -1; + cv.EventID = wfCfg.eventID; + cv.SOE_ID = wfCfg.soeID; cv.Circuit = char(device4); cv.DeviceName = char(device4); - cv.SOEdateTimeLocal = 'Time the SOE begins'; + cv.SOEdateTimeLocal = wfCfg.soeTime; voltagelevel = extract(cv.Circuit,5); voltagelevel = char(voltagelevel); voltCheck = char(device4) @@ -1542,7 +1542,7 @@ function sb = p1_stateChangeDataLogV2SubFunction(action,inLog,newRecords,Circuit end - cv.IncidentID = 'IncidentIDgoesHere'; + cv.IncidentID = wfCfg.incidentID; sb.colValue = cv; % send back assigned values return; end diff --git a/toGPA_G7_Replay/MakeReplay.m b/SEL/toGPA_G7_Replay/MakeReplay.m similarity index 100% rename from toGPA_G7_Replay/MakeReplay.m rename to SEL/toGPA_G7_Replay/MakeReplay.m diff --git a/SEL/toGPA_G7_Replay/SEL_G7_Replay.prj b/SEL/toGPA_G7_Replay/SEL_G7_Replay.prj new file mode 100644 index 0000000..a80644e --- /dev/null +++ b/SEL/toGPA_G7_Replay/SEL_G7_Replay.prj @@ -0,0 +1,139 @@ + + + SEL_G7_Replay + + + 1.0 + + + + + + + + \SEL_G7_Replay\ + option.installpath.programfiles + + + + ${PROJECT_ROOT}\SEL_G7_Replay\for_testing + ${PROJECT_ROOT}\SEL_G7_Replay\for_redistribution_files_only + ${PROJECT_ROOT}\SEL_G7_Replay\for_redistribution + ${PROJECT_ROOT}\SEL_G7_Replay + false + + subtarget.net.component + + SEL_G7_Replay + + true + false + false + MyAppInstaller_web + MyAppInstaller_mcr + MyAppInstaller_app + true + false + + false + false + + false + false + + + SEL_G7_Replay + Analytic + + C:\Projects\epb-matlab\SEL\toGPA_SEL_G7_Replay + + option.cpp.all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${PROJECT_ROOT}\AustinG7.m + + + + + ${PROJECT_ROOT}\AustinG7.m + + + + + + + + + + C:\Projects\epb-matlab\SEL\toGPA_SEL_G7_Replay\SEL_G7_Replay\for_testing\SEL_G7_Replay.dll + C:\Projects\epb-matlab\SEL\toGPA_SEL_G7_Replay\SEL_G7_Replay\for_testing\SEL_G7_Replay_overview.html + C:\Projects\epb-matlab\SEL\toGPA_SEL_G7_Replay\SEL_G7_Replay\for_testing\SEL_G7_ReplayNative.dll + + + + C:\Program Files\MATLAB\R2021b + + + + false + false + true + false + false + false + false + false + 10.0 + false + true + win64 + true + + + \ No newline at end of file diff --git a/SEL/toGPA_G7_Replay/classification.txt b/SEL/toGPA_G7_Replay/classification.txt new file mode 100644 index 0000000..d03bfa6 --- /dev/null +++ b/SEL/toGPA_G7_Replay/classification.txt @@ -0,0 +1,156 @@ +GBBid Active Group Bucket Bin OperatingDevice Outcome Revision TestCount TestResult TestConflict TBD Other +GBB101 Yes Group1 WaveformPresent FiveCycles --- --- Rev2.21 0 NoTest FALSE none none +GBB102 Yes Group1 VoltagePresent TwoDirections --- --- Rev1.50 0 NoTest FALSE none none +GBB103 No Group1 SomeSourceTwoDir 1PH --- --- Rev1.50 0 NoTest FALSE none none +GBB104 No Group1 SomeSourceTwoDir 2PH --- --- Rev1.50 0 NoTest FALSE none none +GBB105 Yes Group1 VoltagePresent OneDirection --- --- Rev1.50 0 NoTest FALSE none none +GBB106 No Group1 SomeSourceAnyDirection 2PH --- --- Rev1.50 0 NoTest FALSE none none +GBB107 No Group1 SomeSourceAnyDirection 1PH --- --- Rev1.50 0 NoTest FALSE none none +GBB108 No Group1 Power PeakCycle --- --- Rev1.50 0 NoTest FALSE none none +GBB109 Yes Group1 Developer Review --- --- Rev1.50 0 NoTest FALSE none none +GBB110 Yes Group1 NoBucket NoBin --- --- Rev1.51 0 NoTest FALSE none none +GBB111 Yes Group1 CurrentPresent FiveCycles --- --- Rev2.38 0 NoTest FALSE none none +GBB201 Yes Group2 Switching LOS sourceSide sourceLost Rev1.50 0 NoTest FALSE none none +GBB202 Yes Group2 Switching sourceReturn sourceSide sourcePresent Rev1.50 0 NoTest FALSE none none +GBB203 Yes Group2 Switching close me energize Rev1.50 0 NoTest FALSE none none +GBB204 Yes Group2 Switching open me de-energize Rev1.50 0 NoTest FALSE none none +GBB205 Yes Group2 Switching closeAddLoad downstream loadIncrease Rev1.50 0 NoTest FALSE none none +GBB206 Yes Group2 Switching openDropLoad downstream loadDecrease Rev1.50 0 NoTest FALSE none none +GBB207 Yes Group2 Switching openRTNorLT me iPresentToInot Rev1.50 0 NoTest FALSE none none +GBB208 Yes Group2 Switching closeRTNorLT me iNotToIpresent Rev1.50 0 NoTest FALSE none none +GBB209 Yes Group2 Developer Review --- --- Rev1.50 0 NoTest FALSE none none +GBB210 Yes Group2 Protection InferredSourceFault sourceSide LOS Rev1.51 0 NoTest FALSE none none +GBB211 Yes Group2 Protection InferredMiscordination sourceSide faultClearByLOS Rev1.51 0 NoTest FALSE none none +GBB212 Yes Group2 Protection Trip me outage Rev1.51 0 NoTest FALSE none none +GBB213 Yes Group2 Protection InferredFaultTrip downstream PQandFaultClear Rev1.51 0 NoTest FALSE none none +GBB214 Yes Group2 Protection InferredTrip parallel sagClear Rev1.51 0 NoTest FALSE none none +GBB215 Yes Group2 ProtectionTripReclose conventionalCase1 upstream sourceReturn Rev1.51 0 NoTest FALSE none none +GBB216 Yes Group2 ProtectionTripReclose conventionalCase2 me restorePower Rev1.51 0 NoTest FALSE none none +GBB217 Yes Group2 ProtectionTripReclose pulseCloseCase1 upstream sourceReturn Rev1.51 0 NoTest FALSE none none +GBB218 Yes Group2 ProtectionTripReclose pulseCloseCase2 me restorePower Rev1.51 0 NoTest FALSE none none +GBB219 Yes Group2 ProtectionTripReclose pulseCloseCase3 downstream loadIncrease Rev1.51 0 NoTest FALSE none none +GBB220 Yes Group2 ProtectionTripReclose hardCloseCase1 upstream sourceReturn Rev1.51 0 NoTest FALSE none none +GBB221 Yes Group2 ProtectionTripReclose hardCloseCase2 me restorePower Rev1.51 0 NoTest FALSE none none +GBB222 Yes Group2 ProtectionTripReclose hardCloseCase3 downstream loadIncrease Rev1.51 0 NoTest FALSE none none +GBB223 Yes Group2 NoBucket NoBin none eyesOnData Rev1.51 0 NoTest FALSE none none +GBB224 Yes Group2 Indeterminate close any eyesOnData Rev1.51 0 NoTest FALSE none none +GBB225 Yes Group2 Indeterminate open any eyesOnData Rev1.51 0 NoTest FALSE none none +GBB230 Yes Group2 Pulse1 Undefined --- --- Rev2.32 0 NoTest FALSE none none +GBB231 Yes Group2 Pulse1 Close me energizePhase1 Rev2.32 0 NoTest FALSE none none +GBB232 Yes Group2 Pulse1 Fault me abortClose Rev2.32 0 NoTest FALSE none none +GBB233 Yes Group2 Inrush1 Fault me abortClose Rev2.32 0 NoTest FALSE none none +GBB234 Yes Group2 Inrush1 CloseFaultReturn me abortClose Rev2.32 0 NoTest FALSE none none +GBB235 Yes Group2 NoPulse1 Waveform --- --- Rev2.32 0 NoTest FALSE none none +GBB236 Yes Group2 Pulse1 NoBin --- --- Rev2.32 0 NoTest FALSE none none +GBB237 Yes Group2 Pulse1 EndOfFile me indeterminate Rev2.32 0 NoTest FALSE none none +GBB238 Yes Group2 Inrush1 Close me energizePhase1 Rev2.32 0 NoTest FALSE none none +GBB240 Yes Group2 Pulse2 Undefined --- --- Rev2.32 0 NoTest FALSE none none +GBB241 Yes Group2 Pulse2 Close me energizePhase2 Rev2.32 0 NoTest FALSE none none +GBB242 Yes Group2 Pulse2 Fault me restorePower Rev2.32 0 NoTest FALSE none none +GBB243 Yes Group2 Inrush2 Fault me restorePower Rev2.32 0 NoTest FALSE none none +GBB244 Yes Group2 Inrush2 CloseFaultReturn me restorePower Rev2.32 0 NoTest FALSE none none +GBB245 Yes Group2 NoPulse2 Waveform --- --- Rev2.32 0 NoTest FALSE none none +GBB246 Yes Group2 Pulse2 NoBin --- --- Rev2.32 0 NoTest FALSE none none +GBB247 Yes Group2 Pulse2 EndOfFile me indeterminate Rev2.32 0 NoTest FALSE none none +GBB248 Yes Group2 Inrush2 Close me energizePhase2 Rev2.32 0 NoTest FALSE none none +GBB250 Yes Group2 Pulse3 Undefined --- --- Rev2.32 0 NoTest FALSE none none +GBB251 Yes Group2 Pulse3 Close me energizePhase2 Rev2.32 0 NoTest FALSE none none +GBB252 Yes Group2 Pulse3 Fault me restorePower Rev2.32 0 NoTest FALSE none none +GBB253 Yes Group2 Inrush3 Fault me restorePower Rev2.32 0 NoTest FALSE none none +GBB254 Yes Group2 Inrush3 CloseFaultReturn me restorePower Rev2.32 0 NoTest FALSE none none +GBB255 Yes Group2 NoPulse3 Waveform --- --- Rev2.32 0 NoTest FALSE none none +GBB256 Yes Group2 Pulse3 NoBin --- --- Rev2.32 0 NoTest FALSE none none +GBB257 Yes Group2 Pulse3 EndOfFile me indeterminate Rev2.32 0 NoTest FALSE none none +GBB258 Yes Group2 Inrush3 Close me energizePhase2 Rev2.32 0 NoTest FALSE none none +GBB301 Yes Group3 PowerQuality persist --- --- Rev1.50 0 NoTest FALSE none none +GBB302 Yes Group3 PowerQuality case1SAG upstream LOS Rev1.50 0 NoTest FALSE none none +GBB303 Yes Group3 PowerQuality case2SAG me trip Rev1.50 0 NoTest FALSE none none +GBB304 Yes Group3 PowerQuality case3SAG parallel clear Rev1.50 0 NoTest FALSE none none +GBB305 Yes Group3 PowerQuality case1Swell upstream LOS Rev1.50 0 NoTest FALSE none none +GBB306 Yes Group3 PowerQuality case2Swell me trip Rev1.50 0 NoTest FALSE none none +GBB307 Yes Group3 PowerQuality case3Swell parallel clear Rev1.50 0 NoTest FALSE none none +GBB308 Yes Group3 Fault persist --- --- Rev1.50 0 NoTest FALSE none none +GBB309 Yes Group3 Fault LGcase1 upstream LOS Rev1.50 0 NoTest FALSE none none +GBB310 Yes Group3 Fault LLcase1 upstream LOS Rev1.50 0 NoTest FALSE none none +GBB311 Yes Group3 Fault LLLcase1 upstream LOS Rev1.50 0 NoTest FALSE none none +GBB312 Yes Group3 Fault LLGcase1 upstream LOS Rev1.50 0 NoTest FALSE none none +GBB313 Yes Group3 Fault LLLGcase1 upstream LOS Rev1.50 0 NoTest FALSE none none +GBB314 Yes Group3 Fault LGcase2 me trip Rev1.50 0 NoTest FALSE none none +GBB315 Yes Group3 Fault LLcase2 me trip Rev1.50 0 NoTest FALSE none none +GBB316 Yes Group3 Fault LLLcase2 me trip Rev1.50 0 NoTest FALSE none none +GBB317 Yes Group3 Fault LLGcase2 me trip Rev1.50 0 NoTest FALSE none none +GBB318 Yes Group3 Fault LLLGcase2 me trip Rev1.50 0 NoTest FALSE none none +GBB319 Yes Group3 Fault LGcase3 downstream clear Rev1.50 0 NoTest FALSE none none +GBB320 Yes Group3 Fault LLcase3 downstream clear Rev1.50 0 NoTest FALSE none none +GBB321 Yes Group3 Fault LLLcase3 downstream clear Rev1.50 0 NoTest FALSE none none +GBB322 Yes Group3 Fault LLGcase3 downstream clear Rev1.50 0 NoTest FALSE none none +GBB323 Yes Group3 Fault LLLGcase2 downstream clear Rev1.50 0 NoTest FALSE none none +GBB324 Yes Group3 Developer Review --- eyesOnData Rev1.50 0 NoTest FALSE none none +GBB325 Yes Group3 Fault LGfuse me trip Rev1.51 0 NoTest FALSE none none +GBB326 Yes Group3 Fault LGfuse downstream clear Rev1.51 0 NoTest FALSE none none +GBB327 Yes Group3 NoFault NoBin none cleanWaveform Rev2.35 0 NoTest FALSE none none +GBB328 Yes Group3 PQandFault Summary any --- Rev1.51 0 NoTest FALSE none none +GBB329 Yes Group3 Fault Short --- --- Rev2.35 0 NoTest FALSE none none +GBB330 Yes Group3 Fault evolving --- --- Rev2.22 0 NoTest FALSE none none +GBB331 Yes Group3 Fault multiple --- --- Rev2.22 0 NoTest FALSE none none +GBB332 Yes Group3 NotPowerQuality NoBin --- --- Rev2.35 0 NoTest FALSE none none +GBB333 Yes Group3 PowerQuality case4SAG downstream clear Rev2.36 0 NoTest FALSE none none +GBB334 Yes Group3 PowerQuality case4Swell downstream clear Rev2.36 0 NoTest FALSE none none +GBB335 Yes Group3 PowerQuality case5SAG indeterminate --- Rev2.36 0 NoTest FALSE none none +GBB336 Yes Group3 PowerQuality case5Swell indeterminate --- Rev2.36 0 NoTest FALSE none none +GBB337 Yes Group3 PowerQuality ExcessSwell --- --- Rev2.37 0 NoTest FALSE none none +GBB401 Yes Group4 Reserved TBD --- --- Rev1.50 0 NoTest FALSE none none +GBB402 Yes Group4 Replay PQpref --- --- Rev1.50 0 NoTest FALSE none none +GBB403 Yes Group4 Replay PQalt --- --- Rev1.50 0 NoTest FALSE none none +GBB404 Yes Group4 Replay Ichange --- --- Rev1.50 0 NoTest FALSE none none +GBB405 Yes Group4 Replay StateEst --- --- Rev1.50 0 NoTest FALSE none none +GBB406 Yes Group4 Developer Details --- --- Rev1.50 0 NoTest FALSE none none +GBB407 Yes Group4 Developer ChangePoints --- --- Rev1.50 0 NoTest FALSE none none +GBB408 Yes Group4 NoBucket NoBin --- --- Rev1.51 0 NoTest FALSE none none +GBB501 Yes Group5 CapRinging Energize any any Rev1.50 0 NoTest FALSE none none +GBB502 Yes Group5 CapRinging FaultResponse any any Rev1.50 0 NoTest FALSE none none +GBB503 Yes Group5 CapRinging PQevent any any Rev1.50 0 NoTest FALSE none none +GBB504 Yes Group5 XfmrMagnetize Energize any any Rev1.50 0 NoTest FALSE none none +GBB505 Yes Group5 XfmrMagnetize FaultResponse any any Rev1.50 0 NoTest FALSE none none +GBB506 Yes Group5 XfmrMagnetize PQevent any any Rev1.50 0 NoTest FALSE none none +GBB507 Yes Group5 Harmonics current any any Rev1.50 0 NoTest FALSE none none +GBB508 Yes Group5 Harmonics voltage any any Rev1.50 0 NoTest FALSE none none +GBB509 Yes Group5 VoltageNotch PositiveSlope any any Rev1.50 0 NoTest FALSE none none +GBB510 Yes Group5 VoltageNotch NegativeSlope any any Rev1.50 0 NoTest FALSE none none +GBB511 Yes Group5 Arcing any any any Rev1.50 0 NoTest FALSE none none +GBB512 Yes Group5 Arcing WireDown any any Rev1.50 0 NoTest FALSE none none +GBB513 Yes Group5 Arcing UGcable any any Rev1.50 0 NoTest FALSE none none +GBB514 Yes Group5 Ferroresonance detected any any Rev1.50 0 NoTest FALSE none none +GBB515 Yes Group5 DCoffset positive any any Rev1.50 0 NoTest FALSE none none +GBB516 Yes Group5 DCoffset negative any any Rev1.50 0 NoTest FALSE none none +GBB517 Yes Group5 DCoffset both any any Rev1.50 0 NoTest FALSE none none +GBB518 Yes Group5 VoltageNotch any any any Rev1.50 0 NoTest FALSE none none +GBB519 Yes Group5 VoltageNotch both any any Rev1.50 0 NoTest FALSE none none +GBB520 Yes Group5 Incipient TBD any any Rev1.50 0 NoTest FALSE none none +GBB521 Yes Group5 NoBucket NoBin --- --- Rev1.51 0 NoTest FALSE none none +GBB522 Yes Group5 Developer Review any any Rev1.51 0 NoTest FALSE none none +GBB601 Yes Group6 MinMaxAvg General --- --- Rev2.15 0 NoTest FALSE none none +GBB602 Yes Group6 MinMaxAvg Voltage --- --- Rev1.50 0 NoTest FALSE none none +GBB603 Yes Group6 MinMaxAvg Current --- --- Rev1.50 0 NoTest FALSE none none +GBB604 Yes Group6 MinMaxAvg PowerVA --- --- Rev1.50 0 NoTest FALSE none none +GBB605 Yes Group6 MinMaxAvg Impedance --- --- Rev1.50 0 NoTest FALSE none none +GBB606 Yes Group6 MinMaxAvg EnergyFirstHalf --- --- Rev1.50 0 NoTest FALSE none none +GBB607 Yes Group6 MinMaxAvg EnergyLastHalf --- --- Rev1.50 0 NoTest FALSE none none +GBB608 Yes Group6 DisturbanceCheck Persists --- --- Rev1.50 0 NoTest FALSE none none +GBB609 Yes Group6 DisturbanceCheck None --- --- Rev1.50 0 NoTest FALSE none none +GBB610 Yes Group6 DisturbanceCheck OneInceptAndClear --- --- Rev1.50 0 NoTest FALSE none none +GBB611 Yes Group6 DisturbanceCheck InceptEqualClear(>1) --- --- Rev1.50 0 NoTest FALSE none none +GBB612 Yes Group6 DisturbanceCheck InceptNEclear(>1) --- --- Rev1.50 0 NoTest FALSE none none +GBB613 Yes Group6 General CurrentImbalance --- --- Rev2.38 0 NoTest FALSE none none +GBB614 Yes Group6 General ClassificationReport --- --- Rev1.50 0 NoTest FALSE none none +GBB615 Yes Group6 General VectorAnalysis --- --- Rev2.41 0 NoTest FALSE none none +GBB620 Yes Group6 General MajorChanges --- --- Rev03.09 0 NoTest FALSE none none +GBB621 Yes Group6 StateChanges History --- --- Rev03.11 0 NoTest FALSE none none +GBB700 Yes Group7 IEEE1668RideThrough NoSag --- --- Rev2.35 0 NoTest FALSE none none +GBB701 Yes Group7 IEEE1668RideThrough SagLG Upstream Clear Rev2.15 0 NoTest FALSE none none +GBB702 Yes Group7 IEEE1668RideThrough SagLL Upstream Clear Rev2.15 0 NoTest FALSE none none +GBB703 Yes Group7 IEEE1668RideThrough SagLLL Upstream Clear Rev2.15 0 NoTest FALSE none none +GBB704 Yes Group7 IEEE1668RideThrough LOS1PH Upstream Clear Rev2.35 0 NoTest FALSE none none +GBB705 Yes Group7 IEEE1668RideThrough LOS2PH Upstream Clear Rev2.35 0 NoTest FALSE none none +GBB706 Yes Group7 IEEE1668RideThrough NoBin --- --- Rev2.35 0 NoTest FALSE none none +GBB999 Yes Group9 TestRecord Ignore --- --- Rev1.51 0 NoTest FALSE none none diff --git a/SEL/toGPA_G7_Replay/colorIndex.txt b/SEL/toGPA_G7_Replay/colorIndex.txt new file mode 100644 index 0000000..d2e6b8e --- /dev/null +++ b/SEL/toGPA_G7_Replay/colorIndex.txt @@ -0,0 +1,14 @@ +0 grayNoFirstWF 150 150 150 +1 redCurrent 255 0 0 +2 blueFault800 0 0 255 +3 ltBluePickUp 110 150 250 +4 greenTrip 0 102 0 +5 greenOpen 0 255 0 +6 redSource 200 0 0 +7 tanPQ 255 170 100 +8 pinkFltPQ 250 5 230 +9 blackLOS 0 0 0 +10 orgSglPH 255 255 0 +11 aquaTBD 5 250 250 +12 dkGrayTBD 250 100 0 +100 yada 1 1 1 \ No newline at end of file diff --git a/toGPA_G7_Replay/groupVoltCurr.m b/SEL/toGPA_G7_Replay/groupVoltCurr.m similarity index 100% rename from toGPA_G7_Replay/groupVoltCurr.m rename to SEL/toGPA_G7_Replay/groupVoltCurr.m diff --git a/SEL/toGPA_G7_Replay/readCFG_COMTRADE.m b/SEL/toGPA_G7_Replay/readCFG_COMTRADE.m new file mode 100644 index 0000000..960665d --- /dev/null +++ b/SEL/toGPA_G7_Replay/readCFG_COMTRADE.m @@ -0,0 +1,135 @@ +function data = readCFG_COMTRADE(filename) + +fid = fopen(filename); % open the configuration file + +qq = fgetl(fid); % read line 1 +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.station_name = ww{:}{1}; +data.recording_device = ww{:}{2}; + +if numel(ww{:})==3 + data.revision_year = ww{:}{3}; +else + data.revision_year = ''; +end + +qq = fgetl(fid); % read line 2 +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.total_channels = str2double(ww{:}{1}); +data.total_analog = str2double(ww{:}{2}(1:end-1)); +data.total_digital = str2double(ww{:}{3}(1:end-1)); + +% channel information + +for la = 1:data.total_analog % loop through each analog channel + + qq = fgetl(fid); % read line + ww = textscan(qq,'%s','delimiter',','); % get individual entries + + data.analog.An(la,1) = ww{:}(1); + + eea = ww{:}(2); + eeb = strrep(eea,'(','_'); % replace brackets with underscore + eec = strrep(eeb,')','_'); % replace brackets with underscore + eed = strrep(eec,'/','_'); % replace forward slashes with underscore + + data.analog.ch_id(la,1) = eed; + + data.analog.ph(la,1) = ww{:}(3); + data.analog.ccbm(la,1) = ww{:}(4); + data.analog.uu(la,1) = ww{:}(5); + data.analog.a(la,1) = str2double(ww{:}(6)); + data.analog.b(la,1) = str2double(ww{:}(7)); + data.analog.skew(la,1) = str2double(ww{:}(8)); + data.analog.min(la,1) = str2double(ww{:}(9)); + data.analog.max(la,1) = str2double(ww{:}(10)); + data.analog.primary(la,1) = str2double(ww{:}(11)); + data.analog.secondary(la,1) = str2double(ww{:}(12)); + data.analog.PS(la,1) = ww{:}(13); + +end + + +for ld = 1:data.total_digital % loop througfh digital channels + + qq = fgetl(fid); % read line + ww = textscan(qq,'%s','delimiter',','); % get individual entries + + data.digital.Dn(ld,1) = ww{:}(1); + + eea = ww{:}(2); + + eeb = strrep(eea,'*',['TEMP',num2str(ld)]); % replace * + eec = strrep(eeb,'/','_'); + + data.digital.ch_id(ld,1) = eec; + data.digital.ph(ld,1) = ww{:}(3); + data.digital.ccbm(ld,1) = ww{:}(4); + data.digital.y(ld,1) = str2double(ww{:}(5)); + +end + +% line frequency + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.lf = str2double(ww{:}); + +% number of rates + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.numrates = str2double(ww{:}); + +% samp, endsamp + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.samp = str2double(ww{:}{1}); +data.endsamp = str2double(ww{:}{2}); + + +% startdate starttime + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.startdate = ww{:}{1}; +data.starttime = ww{:}{2}; + +% triggerdate triggertime + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.triggerdate = ww{:}{1}; +data.triggertime = ww{:}{2}; + +% filetype + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.filetype = ww{:}{1}; + + +% timemult + +qq = fgetl(fid); % read line +ww = textscan(qq,'%s','delimiter',','); % get individual entries + +data.timemult = str2double(ww{:}{1}); + + +fclose(fid); % rwh - mitigates too many files open error + +end + + + + diff --git a/SEL/toGPA_G7_Replay/readDAT_COMTRADE.m b/SEL/toGPA_G7_Replay/readDAT_COMTRADE.m new file mode 100644 index 0000000..3938873 --- /dev/null +++ b/SEL/toGPA_G7_Replay/readDAT_COMTRADE.m @@ -0,0 +1,32 @@ +function data = readDAT_COMTRADE(filename,dataCFG) + +fid = fopen(filename); % open the data file + +nn = repmat('%n',1,dataCFG.total_channels+2); % column format + +ww = textscan(fid,nn,'delimiter',','); % read in the data + + +data.time = ww{2}*1e-6; + +for la = 1:dataCFG.total_analog + + data.analog.(dataCFG.analog.ch_id{la}) = dataCFG.analog.a(la)*ww{la+2} + dataCFG.analog.b(la); + +end + +% Correction for: invalid name field name error +newCh_id = matlab.lang.makeValidName(dataCFG.digital.ch_id); +for ld = 1:dataCFG.total_digital + + %data.digital.(dataCFG.digital.ch_id{ld}) = ww{la+ld+2}; %original + data.digital.(newCh_id{ld}) = ww{la+ld+2}; %correction + +end + +fclose(fid); % rwh - mitigates too many files open error + +end + + +